/* Definitions of target machine for GNU compiler, for the HP Spectrum.
- Copyright (C) 1992, 1993 Free Software Foundation, Inc.
- Contributed by Michael Tiemann (tiemann@mcc.com)
+ Copyright (C) 1992, 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
+ Contributed by Michael Tiemann (tiemann@cygnus.com) of Cygnus Support
and Tim Moore (moore@defmacro.cs.utah.edu) of the Center for
Software Science at the University of Utah.
You should have received a copy of the GNU General Public License
along with GNU CC; see the file COPYING. If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
enum cmp_type /* comparison type */
{
CMP_MAX /* max comparison type */
};
+/* For long call handling. */
+extern unsigned int total_code_bytes;
+
+/* Which processor to schedule for. */
+
+enum processor_type
+{
+ PROCESSOR_700,
+ PROCESSOR_7100,
+ PROCESSOR_7100LC,
+};
+
+#define pa_cpu_attr ((enum attr_cpu)pa_cpu)
+
+/* For -mschedule= option. */
+extern char *pa_cpu_string;
+extern enum processor_type pa_cpu;
+
/* Print subsidiary information on the compiler version in use. */
-#define TARGET_VERSION fprintf (stderr, " (hppa)");
+#define TARGET_VERSION fputs (" (hppa)", stderr);
/* Run-time compilation parameters selecting different hardware subsets. */
#define TARGET_DISABLE_FPREGS (target_flags & 2)
-/* Allow unconditional jumps in the delay slots of call instructions. */
-#define TARGET_JUMP_IN_DELAY (target_flags & 8)
+/* Generate code which assumes that calls through function pointers will
+ never cross a space boundary. Such assumptions are generally safe for
+ building kernels and statically linked executables. Code compiled with
+ this option will fail miserably if the executable is dynamically linked
+ or uses nested functions!
-/* Force all function calls to indirect addressing via a register. This
- avoids lossage when the function is very far away from the current PC.
+ This is also used to trigger agressive unscaled index addressing. */
+#define TARGET_NO_SPACE_REGS (target_flags & 4)
- ??? What about simple jumps, they can suffer from the same problem.
- Would require significant surgery in pa.md. */
+/* Allow unconditional jumps in the delay slots of call instructions. */
+#define TARGET_JUMP_IN_DELAY (target_flags & 8)
-#define TARGET_LONG_CALLS (target_flags & 16)
+/* Optimize for space. Currently this only turns on out of line
+ prologues and epilogues. */
+#define TARGET_SPACE (target_flags & 16)
/* Disable indexed addressing modes. */
HP wants everyone to use for ELF objects. If at all possible you want
to avoid this since it's a performance loss for non-prototyped code.
- Note TARGET_PORTABLE_RUNTIME also implies TARGET_LONG_CALLS. */
+ Note TARGET_PORTABLE_RUNTIME also forces all calls to use inline
+ long-call stubs which is quite expensive. */
#define TARGET_PORTABLE_RUNTIME (target_flags & 64)
#define TARGET_GAS (target_flags & 128)
+/* Emit code for processors which do not have an FPU. */
+
+#define TARGET_SOFT_FLOAT (target_flags & 256)
+
+/* Use 3-insn load/store sequences for access to large data segments
+ 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 }
{"pa-risc-1-0", -1}, \
{"pa-risc-1-1", 1}, \
{"disable-fpregs", 2}, \
- {"no-disable-fpregs", 2}, \
+ {"no-disable-fpregs", -2}, \
+ {"no-space-regs", 4}, \
+ {"space-regs", -4}, \
{"jump-in-delay", 8}, \
{"no-jump-in-delay", -8}, \
- {"long-calls", 16}, \
- {"no-long-calls", -16}, \
+ {"space", 16}, \
+ {"no-space", -16}, \
{"disable-indexing", 32}, \
{"no-disable-indexing", -32},\
- {"portable-runtime", 64+16},\
- {"no-portable-runtime", -(64+16)},\
+ {"portable-runtime", 64}, \
+ {"no-portable-runtime", -64},\
{"gas", 128}, \
{"no-gas", -128}, \
- { "", TARGET_DEFAULT}}
+ {"soft-float", 256}, \
+ {"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_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 OVERRIDE_OPTIONS override_options ()
+
#define DBX_DEBUGGING_INFO
#define DEFAULT_GDB_EXTENSIONS 1
/* This is the way other stabs-in-XXX tools do things. We will be
- compatable. */
+ compatible. */
#define DBX_BLOCKS_FUNCTION_RELATIVE 1
/* Likewise for linenos.
name *first*... */
#define DBX_FUNCTION_FIRST
-/* Only lables should ever begin in colunm zero. */
+/* Only labels should ever begin in column zero. */
#define ASM_STABS_OP "\t.stabs"
#define ASM_STABN_OP "\t.stabn"
((GET_CODE (X) == PLUS ? OFFSET : 0) \
+ (frame_pointer_needed ? 0 : compute_frame_size (get_frame_size (), 0)))
-#if (TARGET_DEFAULT & 1) == 0
+/* gdb needs a null N_SO at the end of each file for scattered loading. */
+
+#undef DBX_OUTPUT_MAIN_SOURCE_FILE_END
+#define DBX_OUTPUT_MAIN_SOURCE_FILE_END(FILE, FILENAME) \
+ text_section (); \
+ if (!TARGET_PORTABLE_RUNTIME) \
+ 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 | 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}"
+ %{mpa-risc-1-1:-D__hp9000s700 -D_PA_RISC1_1}\
+ %{!ansi: -D_HPUX_SOURCE -D_HIUX_SOURCE}"
#else
-#define CPP_SPEC "%{!mpa-risc-1-0:%{!mnosnake:-D__hp9000s700 -D_PA_RISC1_1}}"
+#define CPP_SPEC "%{!mpa-risc-1-0:%{!mnosnake:%{!msoft-float:-D__hp9000s700 -D_PA_RISC1_1}}} %{!ansi: -D_HPUX_SOURCE -D_HIUX_SOURCE}"
#endif
/* Defines for a K&R CC */
#define CC1_SPEC "%{pg:} %{p:}"
-#define LINK_SPEC "-u main"
+#define LINK_SPEC "%{mlinker-opt:-O} %{!shared:-u main} %{shared:-b}"
-/* Allow $ in identifiers. */
-#define DOLLARS_IN_IDENTIFIERS 2
+/* We don't want -lg. */
+#ifndef LIB_SPEC
+#define LIB_SPEC "%{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p}"
+#endif
/* Make gcc agree with <machine/ansi.h> */
#define WCHAR_TYPE "unsigned int"
#define WCHAR_TYPE_SIZE 32
-/* Sometimes certain combinations of command options do not make sense
- on a particular target machine. You can define a macro
- `OVERRIDE_OPTIONS' to take account of this. This macro, if
- defined, is executed once just after all the command options have
- been parsed.
-
- On the PA, it is used to explicitly warn the user that -fpic and -fPIC
- do not work. */
-
-#define OVERRIDE_OPTIONS \
-{ \
- if (flag_pic != 0) \
- warning ("-fpic and -fPIC are not supported on the PA."); \
-}
-
/* Show we can debug even without a frame pointer. */
#define CAN_DEBUG_WITHOUT_FP
+/* Machine dependent reorg pass. */
+#define MACHINE_DEPENDENT_REORG(X) pa_reorg(X)
+
/* Names to predefine in the preprocessor for this target machine. */
-#define CPP_PREDEFINES "-Dhppa -Dhp9000s800 -D__hp9000s800 -Dhp9k8 -Dunix -D_HPUX_SOURCE -Dhp9000 -Dhp800 -Dspectrum -DREVARGV -Asystem(unix) -Asystem(bsd) -Acpu(hppa) -Amachine(hppa)"
+#define CPP_PREDEFINES "-Dhppa -Dhp9000s800 -D__hp9000s800 -Dhp9k8 -Dunix -Dhp9000 -Dhp800 -Dspectrum -DREVARGV -Asystem(unix) -Asystem(bsd) -Acpu(hppa) -Amachine(hppa)"
+
+/* 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"
+ 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, "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)
\f
/* target machine storage layout */
+/* Define for cross-compilation from a host with a different float format
+ or endianness (e.g. VAX, x86). */
+#define REAL_ARITHMETIC
+
+/* Define this macro if it is advisable to hold scalars in registers
+ in a wider mode than that declared by the program. In such cases,
+ the value is constrained to be within the bounds of the declared
+ type, but kept valid in the wider mode. The signedness of the
+ extension may differ from that of the type. */
+
+#define PROMOTE_MODE(MODE,UNSIGNEDP,TYPE) \
+ if (GET_MODE_CLASS (MODE) == MODE_INT \
+ && GET_MODE_SIZE (MODE) < 4) \
+ (MODE) = SImode;
+
/* Define this if most significant bit is lowest numbered
in instructions that operate on numbered bit-fields. */
#define BITS_BIG_ENDIAN 1
/* Define this if most significant word of a multiword number is lowest
numbered. */
-/* For the HP-PA we can decide arbitrarily
- since there are no machine instructions for them. */
#define WORDS_BIG_ENDIAN 1
/* number of bits in an addressable storage unit */
Don't define this if it is equal to PARM_BOUNDARY */
#define MAX_PARM_BOUNDARY 64
-/* Boundary (in *bits*) on which stack pointer should be aligned. */
-#define STACK_BOUNDARY 512
+/* Boundary (in *bits*) on which stack pointer is always aligned;
+ certain optimizations in combine depend on this.
+
+ GCC for the PA always rounds its stacks to a 512bit boundary,
+ but that happens late in the compilation process. */
+#define STACK_BOUNDARY 64
/* Allocation boundary (in *bits*) for the code of a function. */
#define FUNCTION_BOUNDARY 32
Reg 23-26 = Temporary/Parameter Registers
Reg 27 = Global Data Pointer (hp)
Reg 28 = Temporary/???/Return Value register
- Reg 29 = Temporary/Static Chain/Return Value register
+ Reg 29 = Temporary/Static Chain/Return Value register #2
Reg 30 = stack pointer
Reg 31 = Temporary/Millicode Return Pointer (hp)
for (i = 33; i < 88; i += 2) \
fixed_regs[i] = call_used_regs[i] = 1; \
} \
- else if (TARGET_DISABLE_FPREGS) \
+ if (TARGET_DISABLE_FPREGS || TARGET_SOFT_FLOAT)\
{ \
for (i = 32; i < 88; i++) \
fixed_regs[i] = call_used_regs[i] = 1; \
} \
if (flag_pic) \
- fixed_regs[PIC_OFFSET_TABLE_REGNUM] = 1; \
+ { \
+ fixed_regs[PIC_OFFSET_TABLE_REGNUM] = 1; \
+ fixed_regs[PIC_OFFSET_TABLE_REGNUM_SAVED] = 1;\
+ } \
}
/* Allocate the call used registers first. This should minimize
#define REG_ALLOC_ORDER \
{ \
/* caller-saved fp regs. */ \
- 40, 41, 42, 43, 44, 45, 46, 47, \
68, 69, 70, 71, 72, 73, 74, 75, \
76, 77, 78, 79, 80, 81, 82, 83, \
84, 85, 86, 87, \
+ 40, 41, 42, 43, 44, 45, 46, 47, \
32, 33, 34, 35, 36, 37, 38, 39, \
/* caller-saved general regs. */ \
19, 20, 21, 22, 23, 24, 25, 26, \
/* 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.
data references. */
#define PIC_OFFSET_TABLE_REGNUM 19
+#define PIC_OFFSET_TABLE_REG_CALL_CLOBBERED 1
-#define FINALIZE_PIC finalize_pic ()
+/* Register into which we save the PIC_OFFEST_TABLE_REGNUM so that it
+ can be restore across function calls. */
+#define PIC_OFFSET_TABLE_REGNUM_SAVED 4
/* SOM ABI says that objects larger than 64 bits are returned in memory. */
+#define DEFAULT_PCC_STRUCT_RETURN 0
#define RETURN_IN_MEMORY(TYPE) \
- (TYPE_MODE (TYPE) == BLKmode || int_size_in_bytes (TYPE) > 8)
+ (int_size_in_bytes (TYPE) > 8)
/* Register in which address to store a structure value
is passed to a function. */
#define PREFERRED_RELOAD_CLASS(X,CLASS) (CLASS)
/* Return the register class of a scratch register needed to copy IN into
- or out of a register in CLASS in MODE. If it can be done directly,
- NO_REGS is returned. */
+ or out of a register in CLASS in MODE. If it can be done directly
+ NO_REGS is returned.
+
+ Avoid doing any work for the common case calls. */
#define SECONDARY_RELOAD_CLASS(CLASS,MODE,IN) \
- secondary_reload_class (CLASS, MODE, IN)
+ ((CLASS == BASE_REG_CLASS && GET_CODE (IN) == REG \
+ && REGNO (IN) < FIRST_PSEUDO_REGISTER) \
+ ? NO_REGS : secondary_reload_class (CLASS, MODE, IN))
/* On the PA it is not possible to directly move data between
GENERAL_REGS and FP_REGS. */
/* Value is 1 if returning from a function call automatically
pops the arguments described by the number-of-args field in the call.
+ FUNDECL is the declaration node of the function (as a tree),
FUNTYPE is the data type of the function (as a tree),
or for a library call it is an identifier node for the subroutine name. */
-#define RETURN_POPS_ARGS(FUNTYPE,SIZE) 0
+#define RETURN_POPS_ARGS(FUNDECL,FUNTYPE,SIZE) 0
/* Define how to find the value returned by a function.
VALTYPE is the data type of the value (as a tree).
#define FUNCTION_VALUE(VALTYPE, FUNC) \
- gen_rtx (REG, TYPE_MODE (VALTYPE), ((TYPE_MODE (VALTYPE) == SFmode || \
- TYPE_MODE (VALTYPE) == DFmode) ? \
+ gen_rtx (REG, TYPE_MODE (VALTYPE), ((! TARGET_SOFT_FLOAT \
+ && (TYPE_MODE (VALTYPE) == SFmode || \
+ TYPE_MODE (VALTYPE) == DFmode)) ? \
32 : 28))
/* Define how to find the value returned by a library function
assuming the value has mode MODE. */
-#define LIBCALL_VALUE(MODE) \
- gen_rtx (REG, MODE, ((MODE) == SFmode || (MODE) == DFmode ? 32 : 28))
+#define LIBCALL_VALUE(MODE) \
+ gen_rtx (REG, MODE, \
+ (! TARGET_SOFT_FLOAT \
+ && ((MODE) == SFmode || (MODE) == DFmode) ? 32 : 28))
/* 1 if N is a possible register number for a function value
as seen by the caller. */
#define FUNCTION_VALUE_REGNO_P(N) \
- ((N) == 28 || (N) == 32)
+ ((N) == 28 || (! TARGET_SOFT_FLOAT && (N) == 32))
/* 1 if N is a possible register number for function argument passing. */
#define FUNCTION_ARG_REGNO_P(N) \
- (((N) >= 23 && (N) <= 26) || ((N) >= 32 && (N) <= 39))
+ (((N) >= 23 && (N) <= 26) || (! TARGET_SOFT_FLOAT && (N) >= 32 && (N) <= 39))
\f
/* Define a data type for recording info about an argument list
during the scan of that argument list. This data type should
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. */
The caller must make a distinction between calls to explicitly named
functions and calls through pointers to functions -- the conventions
are different! Calls through pointers to functions only use general
- registers for the first four argument words. Note the indirect function
- calling conventions are in effect during TARGET_LONG_CALLS, but
- current_call_is_indirect will not be set in such situations.
+ registers for the first four argument words.
Of course all this is different for the portable runtime model
HP wants everyone to use for ELF. Ugh. Here's a quick description
#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \
(4 >= ((CUM).words + FUNCTION_ARG_SIZE ((MODE), (TYPE))) \
? (!TARGET_PORTABLE_RUNTIME || (TYPE) == 0 \
- || !FLOAT_MODE_P (MODE) || (CUM).nargs_prototype > 0) \
+ || !FLOAT_MODE_P (MODE) || TARGET_SOFT_FLOAT \
+ || (CUM).nargs_prototype > 0) \
? gen_rtx (REG, (MODE), \
(FUNCTION_ARG_SIZE ((MODE), (TYPE)) > 1 \
- ? (((!(current_call_is_indirect || TARGET_LONG_CALLS) \
+ ? (((!(CUM).indirect \
|| TARGET_PORTABLE_RUNTIME) \
- && (MODE) == DFmode) \
+ && (MODE) == DFmode \
+ && ! TARGET_SOFT_FLOAT) \
? ((CUM).words ? 38 : 34) \
: ((CUM).words ? 23 : 25)) \
- : (((!(current_call_is_indirect || TARGET_LONG_CALLS) \
+ : (((!(CUM).indirect \
|| TARGET_PORTABLE_RUNTIME) \
- && (MODE) == SFmode) \
+ && (MODE) == SFmode \
+ && ! TARGET_SOFT_FLOAT) \
? (32 + 2 * (CUM).words) \
: (27 - (CUM).words - FUNCTION_ARG_SIZE ((MODE), \
(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)
#define FUNCTION_ARG_PASS_BY_REFERENCE(CUM, MODE, TYPE, NAMED) \
((TYPE) && int_size_in_bytes (TYPE) > 8)
+
+#define FUNCTION_ARG_CALLEE_COPIES(CUM, MODE, TYPE, NAMED) \
+ ((TYPE) && int_size_in_bytes (TYPE) > 8)
+
\f
extern struct rtx_def *hppa_compare_op0, *hppa_compare_op1;
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; \
+ STRIP_NAME_ENCODING (name, NAME); \
+ if (!TARGET_PORTABLE_RUNTIME && TARGET_GAS && in_section == in_text) \
+ fputs ("\t.NSUBSPA $CODE$,QUAD=0,ALIGN=8,ACCESS=44,CODE_ONLY\n", FILE); \
+ else if (! TARGET_PORTABLE_RUNTIME && TARGET_GAS) \
+ fprintf (FILE, \
+ "\t.SUBSPA %s\n", name); \
+ }
+
#define ASM_DECLARE_FUNCTION_NAME(FILE, NAME, DECL) \
do { tree fntype = TREE_TYPE (TREE_TYPE (DECL)); \
tree tree_type = TREE_TYPE (DECL); \
for (parm = DECL_ARGUMENTS (DECL), i = 0; parm && i < 4; \
parm = TREE_CHAIN (parm)) \
{ \
- if (TYPE_MODE (DECL_ARG_TYPE (parm)) == SFmode) \
+ if (TYPE_MODE (DECL_ARG_TYPE (parm)) == SFmode \
+ && ! TARGET_SOFT_FLOAT) \
fprintf (FILE, ",ARGW%d=FR", i++); \
- else if (TYPE_MODE (DECL_ARG_TYPE (parm)) == DFmode) \
+ else if (TYPE_MODE (DECL_ARG_TYPE (parm)) == DFmode \
+ && ! TARGET_SOFT_FLOAT) \
{ \
if (i <= 2) \
{ \
int arg_size = \
FUNCTION_ARG_SIZE (TYPE_MODE (DECL_ARG_TYPE (parm)),\
DECL_ARG_TYPE (parm)); \
+ /* Passing structs by invisible reference uses \
+ one general register. */ \
+ if (arg_size > 2 \
+ || TREE_ADDRESSABLE (DECL_ARG_TYPE (parm))) \
+ arg_size = 1; \
if (arg_size == 2 && i <= 2) \
{ \
if (i == 1) i++; \
for (; i < 4; i++) \
fprintf (FILE, ",ARGW%d=GR", i); \
} \
- if (TYPE_MODE (fntype) == DFmode) \
- fprintf (FILE, ",RTNVAL=FR"); \
- else if (TYPE_MODE (fntype) == SFmode) \
- fprintf (FILE, ",RTNVAL=FU"); \
+ if (TYPE_MODE (fntype) == DFmode && ! TARGET_SOFT_FLOAT) \
+ fputs (",RTNVAL=FR", FILE); \
+ else if (TYPE_MODE (fntype) == SFmode && ! TARGET_SOFT_FLOAT) \
+ fputs (",RTNVAL=FU", FILE); \
else if (fntype != void_type_node) \
- fprintf (FILE, ",RTNVAL=GR"); \
+ fputs (",RTNVAL=GR", FILE); \
fputs ("\n", FILE); \
}} while (0)
#define TRAMPOLINE_TEMPLATE(FILE) \
{ \
- fprintf (FILE, "\tldw 36(0,%%r22),%%r21\n"); \
- fprintf (FILE, "\tbb,>=,n %%r21,30,.+16\n"); \
- fprintf (FILE, "\tdepi 0,31,2,%%r21\n"); \
- fprintf (FILE, "\tldw 4(0,%%r21),%%r19\n"); \
- fprintf (FILE, "\tldw 0(0,%%r21),%%r21\n"); \
- fprintf (FILE, "\tldsid (0,%%r21),%%r1\n"); \
- fprintf (FILE, "\tmtsp %%r1,%%sr0\n"); \
- fprintf (FILE, "\tbe 0(%%sr0,%%r21)\n"); \
- fprintf (FILE, "\tldw 40(0,%%r22),%%r29\n"); \
- fprintf (FILE, "\t.word 0\n"); \
- fprintf (FILE, "\t.word 0\n"); \
+ fputs ("\tldw 36(0,%r22),%r21\n", FILE); \
+ fputs ("\tbb,>=,n %r21,30,.+16\n", FILE); \
+ fputs ("\tdepi 0,31,2,%r21\n", FILE); \
+ fputs ("\tldw 4(0,%r21),%r19\n", FILE); \
+ fputs ("\tldw 0(0,%r21),%r21\n", FILE); \
+ fputs ("\tldsid (0,%r21),%r1\n", FILE); \
+ fputs ("\tmtsp %r1,%sr0\n", FILE); \
+ fputs ("\tbe 0(%sr0,%r21)\n", FILE); \
+ fputs ("\tldw 40(0,%r22),%r29\n", FILE); \
+ fputs ("\t.word 0\n", FILE); \
+ fputs ("\t.word 0\n", FILE); \
}
/* Length in units of the trampoline for entering a nested function.
Ordinarily they are not call used registers, but they are for
_builtin_saveregs, so we must make this explicit. */
-#define EXPAND_BUILTIN_SAVEREGS(ARGLIST) (rtx)hppa_builtin_saveregs (ARGLIST)
+extern struct rtx_def *hppa_builtin_saveregs ();
+#define EXPAND_BUILTIN_SAVEREGS(ARGLIST) hppa_builtin_saveregs (ARGLIST)
\f
/* Addressing modes, and classification of registers for them. */
floating-point, except for floating-point zero. */
#define LEGITIMATE_CONSTANT_P(X) \
- (GET_MODE_CLASS (GET_MODE (X)) != MODE_FLOAT \
- || (X) == CONST0_RTX (GET_MODE (X)))
+ ((GET_MODE_CLASS (GET_MODE (X)) != MODE_FLOAT \
+ || (X) == CONST0_RTX (GET_MODE (X))) \
+ && !(flag_pic && function_label_operand (X, VOIDmode)))
/* Subroutine for EXTRA_CONSTRAINT.
these things in insns and then not re-recognize the insns, causing
constrain_operands to fail.
- Also note `Q' accepts any memory operand during the reload pass.
- This includes out-of-range displacements in reg+d addressing.
- This makes for better code. (??? For 2.5 address this issue).
-
`R' is unused.
`S' is unused.
#define EXTRA_CONSTRAINT(OP, C) \
((C) == 'Q' ? \
(IS_RELOADING_PSEUDO_P (OP) \
- || (GET_CODE (OP) == MEM \
- && reload_in_progress) \
|| (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.
&& REG_OK_FOR_BASE_P (XEXP (X, 1))) \
goto ADDR; \
else if (flag_pic == 1 \
- && GET_CODE (XEXP (X, 1)) != REG \
- && GET_CODE (XEXP (X, 1)) != LO_SUM \
- && GET_CODE (XEXP (X, 1)) != MEM) \
+ && GET_CODE (XEXP (X, 1)) == SYMBOL_REF)\
goto ADDR; \
} \
else if (REG_P (XEXP (X, 0)) \
base = XEXP (X, 1), index = XEXP (X, 0); \
if (base != 0) \
if (GET_CODE (index) == CONST_INT \
- && ((INT_14_BITS (index) && (MODE) != SFmode && (MODE) != DFmode) \
+ && ((INT_14_BITS (index) \
+ && (TARGET_SOFT_FLOAT \
+ || ((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 \
&& REG_OK_FOR_BASE_P (XEXP (X, 0)) \
&& CONSTANT_P (XEXP (X, 1)) \
- && (MODE) != SFmode \
- && (MODE) != DFmode) \
+ && (TARGET_SOFT_FLOAT \
+ || ((MODE) != SFmode \
+ && (MODE) != DFmode))) \
goto ADDR; \
else if (GET_CODE (X) == LO_SUM \
&& GET_CODE (XEXP (X, 0)) == SUBREG \
&& GET_CODE (SUBREG_REG (XEXP (X, 0))) == REG\
&& REG_OK_FOR_BASE_P (SUBREG_REG (XEXP (X, 0)))\
&& CONSTANT_P (XEXP (X, 1)) \
- && (MODE) != SFmode \
- && (MODE) != DFmode) \
+ && (TARGET_SOFT_FLOAT \
+ || ((MODE) != SFmode \
+ && (MODE) != DFmode))) \
goto ADDR; \
else if (GET_CODE (X) == LABEL_REF \
|| (GET_CODE (X) == CONST_INT \
&& INT_5_BITS (X))) \
goto ADDR; \
+ /* Needed for -fPIC */ \
+ else if (GET_CODE (X) == LO_SUM \
+ && GET_CODE (XEXP (X, 0)) == REG \
+ && REG_OK_FOR_BASE_P (XEXP (X, 0)) \
+ && GET_CODE (XEXP (X, 1)) == UNSPEC) \
+ goto ADDR; \
}
\f
/* Try machine-dependent ways of modifying an illegitimate 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)))
_rtl = TREE_CST_RTL (DECL); \
SYMBOL_REF_FLAG (XEXP (_rtl, 0)) = 1; \
if (TREE_CODE (DECL) == FUNCTION_DECL) \
- hppa_encode_label (XEXP (DECL_RTL (DECL), 0));\
+ hppa_encode_label (XEXP (DECL_RTL (DECL), 0), 0);\
} \
} \
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
+ if a particular label in the constant pool refers to a function address.
+ So just force everything into the data space during PIC generation. */
+#define SELECT_RTX_SECTION(RTX,MODE) \
+ if (flag_pic) \
+ data_section (); \
+ else \
+ readonly_data_section ();
+
/* Specify the machine mode that this machine uses
for the index in the tablejump instruction. */
#define CASE_VECTOR_MODE DImode
in one reasonably fast instruction. */
#define MOVE_MAX 8
+/* Higher than the default as we prefer to use simple move insns
+ (better scheduling and delay slot filling) and because our
+ built-in block move is really a 2X unrolled loop. */
+#define MOVE_RATIO 4
+
/* Define if operations between registers always perform the operation
on the full register even if a narrower mode is specified. */
#define WORD_REGISTER_OPERATIONS
#define SLOW_BYTE_ACCESS 1
/* Do not break .stabs pseudos into continuations. */
-#define DBX_CONTIN_LENGTH 0
+#define DBX_CONTIN_LENGTH 4000
/* Value is 1 if truncating an integer of INPREC bits to OUTPREC bits
is done just by pretending it is already truncated. */
switch on CODE. The purpose for the cost of MULT is to encourage
`synth_mult' to find a synthetic multiply when reasonable. */
-#define RTX_COSTS(X,CODE,OUTER_CODE) \
- case MULT: \
- return TARGET_SNAKE && ! TARGET_DISABLE_FPREGS \
- ? COSTS_N_INSNS (8) : COSTS_N_INSNS (20); \
- case DIV: \
- case UDIV: \
- case MOD: \
- case UMOD: \
- return COSTS_N_INSNS (60); \
- case PLUS: \
- if (GET_CODE (XEXP (X, 0)) == MULT \
- && shadd_operand (XEXP (XEXP (X, 0), 1), VOIDmode)) \
- return (2 + rtx_cost (XEXP (XEXP (X, 0), 0), OUTER_CODE) \
- + rtx_cost (XEXP (X, 1), OUTER_CODE)); \
- break;
+#define RTX_COSTS(X,CODE,OUTER_CODE) \
+ case MULT: \
+ if (GET_MODE_CLASS (GET_MODE (X)) == MODE_FLOAT) \
+ return COSTS_N_INSNS (3); \
+ return (TARGET_SNAKE && ! TARGET_DISABLE_FPREGS && ! TARGET_SOFT_FLOAT) \
+ ? COSTS_N_INSNS (8) : COSTS_N_INSNS (20); \
+ case DIV: \
+ if (GET_MODE_CLASS (GET_MODE (X)) == MODE_FLOAT) \
+ return COSTS_N_INSNS (14); \
+ case UDIV: \
+ case MOD: \
+ case UMOD: \
+ return COSTS_N_INSNS (60); \
+ case PLUS: /* this includes shNadd insns */ \
+ case MINUS: \
+ if (GET_MODE_CLASS (GET_MODE (X)) == MODE_FLOAT) \
+ return COSTS_N_INSNS (3); \
+ return COSTS_N_INSNS (1); \
+ case ASHIFT: \
+ case ASHIFTRT: \
+ case LSHIFTRT: \
+ return COSTS_N_INSNS (1);
/* Adjust the cost of dependencies. */
#define ADJUST_COST(INSN,LINK,DEP,COST) \
(COST) = pa_adjust_cost (INSN, LINK, DEP, COST)
+/* Adjust scheduling priorities. We use this to try and keep addil
+ and the next use of %r1 close together. */
+#define ADJUST_PRIORITY(PREV) \
+ { \
+ rtx set = single_set (PREV); \
+ rtx src, dest; \
+ if (set) \
+ { \
+ src = SET_SRC (set); \
+ dest = SET_DEST (set); \
+ if (GET_CODE (src) == LO_SUM \
+ && symbolic_operand (XEXP (src, 1), VOIDmode) \
+ && ! read_only_operand (XEXP (src, 1), VOIDmode)) \
+ INSN_PRIORITY (PREV) >>= 3; \
+ else if (GET_CODE (src) == MEM \
+ && GET_CODE (XEXP (src, 0)) == LO_SUM \
+ && symbolic_operand (XEXP (XEXP (src, 0), 1), VOIDmode)\
+ && ! read_only_operand (XEXP (XEXP (src, 0), 1), VOIDmode))\
+ INSN_PRIORITY (PREV) >>= 1; \
+ else if (GET_CODE (dest) == MEM \
+ && GET_CODE (XEXP (dest, 0)) == LO_SUM \
+ && symbolic_operand (XEXP (XEXP (dest, 0), 1), VOIDmode)\
+ && ! read_only_operand (XEXP (XEXP (dest, 0), 1), VOIDmode))\
+ INSN_PRIORITY (PREV) >>= 3; \
+ } \
+ }
+
/* Handling the special cases is going to get too complicated for a macro,
just call `pa_adjust_insn_length' to do the real work. */
#define ADJUST_INSN_LENGTH(INSN, LENGTH) \
/* Output at beginning of assembler file. */
#define ASM_FILE_START(FILE) \
-do { fprintf (FILE, "\t.SPACE $PRIVATE$\n\
+do { fputs ("\t.SPACE $PRIVATE$\n\
\t.SUBSPA $DATA$,QUAD=1,ALIGN=8,ACCESS=31\n\
\t.SUBSPA $BSS$,QUAD=1,ALIGN=8,ACCESS=31,ZERO,SORT=82\n\
\t.SPACE $TEXT$\n\
\t.SUBSPA $LIT$,QUAD=0,ALIGN=8,ACCESS=44\n\
\t.SUBSPA $CODE$,QUAD=0,ALIGN=8,ACCESS=44,CODE_ONLY\n\
\t.IMPORT $global$,DATA\n\
-\t.IMPORT $$dyncall,MILLICODE\n");\
+\t.IMPORT $$dyncall,MILLICODE\n", FILE);\
if (profile_flag)\
fprintf (FILE, "\t.IMPORT _mcount, CODE\n");\
if (write_symbols != NO_DEBUG) \
#define ASM_APP_OFF ""
/* We don't yet know how to identify GCC to HP-PA machines. */
-#define ASM_IDENTIFY_GCC(FILE) fprintf (FILE, "; gcc_compiled.:\n")
+#define ASM_IDENTIFY_GCC(FILE) fputs ("; gcc_compiled.:\n", FILE)
/* Output before code. */
/* Define the .bss section for ASM_OUTPUT_LOCAL to use. */
-#define EXTRA_SECTIONS in_bss, in_readonly_data
+#ifndef CTORS_SECTION_FUNCTION
+#define EXTRA_SECTIONS in_readonly_data
+#define CTORS_SECTION_FUNCTION
+#define DTORS_SECTION_FUNCTION
+#else
+#define EXTRA_SECTIONS in_readonly_data, in_ctors, in_dtors
+#endif
+
+/* Switch into a generic section.
+ This is currently only used to support section attributes.
+
+ We make the section read-only and executable for a function decl,
+ read-only for a const data decl, and writable for a non-const data decl. */
+#define ASM_OUTPUT_SECTION_NAME(FILE, DECL, NAME) \
+ if (DECL && TREE_CODE (DECL) == FUNCTION_DECL) \
+ { \
+ fputs ("\t.SPACE $TEXT$\n", FILE); \
+ fprintf (FILE, \
+ "\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%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", \
+ TARGET_GAS ? "" : "$", NAME, TARGET_GAS ? "" : "$"); \
+ }
+
+/* FIXME: HPUX ld generates incorrect GOT entries for "T" fixups
+ which reference data within the $TEXT$ space (for example constant
+ strings in the $LIT$ subspace).
+
+ The assemblers (GAS and HP as) both have problems with handling
+ the difference of two symbols which is the other correct way to
+ reference constant data during PIC code generation.
+
+ So, there's no way to reference constant data which is in the
+ $TEXT$ space during PIC generation. Instead place all constant
+ data into the $PRIVATE$ subspace (this reduces sharing, but it
+ works correctly). */
#define EXTRA_SECTION_FUNCTIONS \
void \
-bss_section () \
-{ \
- if (in_section != in_bss) \
- { \
- fprintf (asm_out_file, "%s\n", BSS_SECTION_ASM_OP); \
- in_section = in_bss; \
- } \
-} \
-void \
readonly_data () \
{ \
if (in_section != in_readonly_data) \
{ \
- fprintf (asm_out_file, "%s\n", READONLY_DATA_ASM_OP); \
+ if (flag_pic) \
+ fprintf (asm_out_file, "%s\n", DATA_SECTION_ASM_OP); \
+ else \
+ fprintf (asm_out_file, "%s\n", READONLY_DATA_ASM_OP); \
in_section = in_readonly_data; \
} \
-}
+} \
+CTORS_SECTION_FUNCTION \
+DTORS_SECTION_FUNCTION
/* How to refer to registers in assembler output.
fputc ('\n', FILE); } while (0)
/* This is how to output a command to make the user-level label named NAME
- defined for reference from other files. */
+ defined for reference from other files.
+
+ We call assemble_name, which in turn sets TREE_SYMBOL_REFERENCED. This
+ macro will restore the original value of TREE_SYMBOL_REFERENCED to avoid
+ placing useless function definitions in the output file. */
#define ASM_OUTPUT_EXTERNAL(FILE, DECL, NAME) \
- do { fputs ("\t.IMPORT ", FILE); \
+ do { int save_referenced; \
+ save_referenced = TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (DECL)); \
+ fputs ("\t.IMPORT ", FILE); \
assemble_name (FILE, NAME); \
if (FUNCTION_NAME_P (NAME)) \
fputs (",CODE\n", FILE); \
else \
fputs (",DATA\n", FILE); \
- } while (0)
-
-/* hpux ld doesn't output the object file name, or anything useful at
- all, to indicate the start of an object file's symbols. This screws
- up gdb, so we'll output this magic cookie at the end of an object
- file with debugging symbols */
-
-#define ASM_FILE_END(FILE) \
- do { if (write_symbols == DBX_DEBUG)\
- { fputs (TEXT_SECTION_ASM_OP, FILE);\
- fputs ("\t.stabs \"end_file.\",4,0,0,Ltext_end\nLtext_end:\n",\
- (FILE));\
- }\
+ TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (DECL)) = save_referenced; \
} while (0)
/* The bogus HP assembler requires ALL external references to be
"imported", even library calls. They look a bit different, so
- here's this macro. */
+ here's this macro.
+
+ Also note not all libcall names are passed to ENCODE_SECTION_INFO
+ (__main for example). To make sure all libcall names have section
+ info recorded in them, we do it here. */
#define ASM_OUTPUT_EXTERNAL_LIBCALL(FILE, RTL) \
do { fputs ("\t.IMPORT ", FILE); \
+ if (!function_label_operand (RTL, VOIDmode)) \
+ hppa_encode_label (RTL, 1); \
assemble_name (FILE, XSTR ((RTL), 0)); \
fputs (",CODE\n", FILE); \
} while (0)
/* This is how to output an assembler line defining a `double' constant. */
#define ASM_OUTPUT_DOUBLE(FILE,VALUE) \
- do { union { double d; int i[2];} __u; \
- __u.d = (VALUE); \
- fprintf (FILE, "\t; .double %.20e\n\t.word %d ; = 0x%x\n\t.word %d ; = 0x%x\n", \
- __u.d, __u.i[0], __u.i[0], __u.i[1], __u.i[1]); \
- } while (0)
+ do { long l[2]; \
+ REAL_VALUE_TO_TARGET_DOUBLE (VALUE, l); \
+ fprintf (FILE, "\t.word 0x%lx\n\t.word 0x%lx\n", l[0], l[1]); \
+ } while (0)
/* This is how to output an assembler line defining a `float' constant. */
#define ASM_OUTPUT_FLOAT(FILE,VALUE) \
- do { union { float f; int i;} __u; \
- __u.f = (VALUE); \
- fprintf (FILE, "\t; .float %.12e\n\t.word %d ; = 0x%x\n", __u.f, __u.i, __u.i); \
- } while (0)
+ do { long l; \
+ REAL_VALUE_TO_TARGET_SINGLE (VALUE, l); \
+ fprintf (FILE, "\t.word 0x%lx\n", l); \
+ } while (0)
+
+/* This is how to output an assembler line defining an `int' constant.
-/* This is how to output an assembler line defining an `int' constant. */
+ This is made more complicated by the fact that functions must be
+ prefixed by a P% as well as code label references for the exception
+ table -- otherwise the linker chokes. */
#define ASM_OUTPUT_INT(FILE,VALUE) \
-{ fprintf (FILE, "\t.word "); \
+{ fputs ("\t.word ", FILE); \
if (function_label_operand (VALUE, VOIDmode) \
&& !TARGET_PORTABLE_RUNTIME) \
- fprintf (FILE, "P%%"); \
+ fputs ("P%", FILE); \
output_addr_const (FILE, (VALUE)); \
- fprintf (FILE, "\n");}
+ fputs ("\n", FILE);}
/* Likewise for `short' and `char' constants. */
#define ASM_OUTPUT_SHORT(FILE,VALUE) \
-( fprintf (FILE, "\t.half "), \
+( fputs ("\t.half ", FILE), \
output_addr_const (FILE, (VALUE)), \
- fprintf (FILE, "\n"))
+ fputs ("\n", FILE))
#define ASM_OUTPUT_CHAR(FILE,VALUE) \
-( fprintf (FILE, "\t.byte "), \
+( fputs ("\t.byte ", FILE), \
output_addr_const (FILE, (VALUE)), \
- fprintf (FILE, "\n"))
+ fputs ("\n", FILE))
/* This is how to output an assembler line for a numeric constant byte. */
/* This is how to output an element of a case-vector that is relative.
This must be defined correctly as it is used when generating PIC code.
- I belive it safe to use the same definition as ASM_OUTPUT_ADDR_VEC_ELT
+ I believe it safe to use the same definition as ASM_OUTPUT_ADDR_VEC_ELT
on the PA since ASM_OUTPUT_ADDR_VEC_ELT uses pc-relative jump instructions
rather than a table of absolute addresses. */
fprintf (FILE, "%d(0,%s)", offset, reg_names [REGNO (base)]); \
break; \
case LO_SUM: \
- fputs ("R'", FILE); \
- output_global_address (FILE, XEXP (addr, 1)); \
+ if (!symbolic_operand (XEXP (addr, 1))) \
+ fputs ("R'", FILE); \
+ else if (flag_pic == 0) \
+ fputs ("RR'", FILE); \
+ else if (flag_pic == 1) \
+ abort (); \
+ else if (flag_pic == 2) \
+ fputs ("RT'", FILE); \
+ output_global_address (FILE, XEXP (addr, 1), 0); \
fputs ("(", FILE); \
output_operand (XEXP (addr, 0), 0); \
fputs (")", FILE); \
extern char *output_block_move ();
extern char *output_cbranch ();
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 ();
extern char *output_mul_insn ();
extern char *output_div_insn ();
extern char *output_mod_insn ();
extern struct rtx_def *gen_cmp_fp ();
extern void hppa_encode_label ();
-extern struct rtx_def *hppa_save_pic_table_rtx;
-
-#if 0
-#define PREDICATE_CODES \
- {"reg_or_0_operand", {SUBREG, REG, CONST_INT}}, \
- {"reg_or_cint_move_operand", {SUBREG, REG, CONST_INT}}, \
- {"arith_operand", {SUBREG, REG, CONST_INT}}, \
- {"arith32_operand", {SUBREG, REG, CONST_INT}}, \
- {"arith11_operand", {SUBREG, REG, CONST_INT}}, \
- {"arith5_operand", {SUBREG, REG, CONST_INT}}, \
- {"pre_cint_operand", {CONST_INT}}, \
- {"post_cint_operand", {CONST_INT}}, \
- {"int5_operand", {CONST_INT}}, \
- {"uint5_operand", {CONST_INT}}, \
- {"uint32_operand", {CONST_INT}}, \
- {"int11_operand", {CONST_INT}}, \
- {"and_operand", {SUBREG, REG, CONST_INT}}, \
- {"ior_operand", {CONST_INT}}, \
- {"lhs_lshift_operand", {SUBREG, REG, CONST_INT}}, \
- {"lhs_lshift_cint_operand", {CONST_INT}}, \
- {"plus_xor_ior_operator", {PLUS, XOR, IOR}}, \
- {"shadd_operand", {CONST_INT}}, \
- {"eq_neq_comparison_operator", {EQ, NE}}, \
- {"movb_comparison_operator", {EQ, NE, LT, GE}}, \
- {"pc_or_label_operand", {LABEL_REF, PC}}, \
- {"symbolic_operand", {SYMBOL_REF, LABEL_REF, CONST}}, \
- {"reg_or_nonsymb_mem_operand", {REG, SUBREG, MEM}}, \
- {"move_operand", {REG, SUBREG, CONST_INT, MEM}}, \
- {"pic_operand", {REG, SUBREG, CONST_INT, SYMBOL_REF, LABEL_REF, \
- CONST, HIGH, PC}}, /* No clue */ \
- {"function_label_operand", {SYMBOL_REF}}, \
- {"reg_or_0_or_nonsymb_mem_operand", {REG, SUBREG, CONST_INT, MEM}}, \
- {"div_operand", {REG, CONST_INT}}, \
- {"call_operand_address", {LABEL_REF, SYMBOL_REF, CONST_INT, \
- CONST, HIGH}},
-#endif
+/* 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++) (); \
+} 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