--- gcc/config/pa/pa.h 2018/04/24 18:23:44 1.1.1.3 +++ gcc/config/pa/pa.h 2018/04/24 18:36:29 1.1.1.5 @@ -1,6 +1,6 @@ /* 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 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. @@ -18,7 +18,8 @@ GNU General Public License for more deta 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 */ { @@ -28,6 +29,24 @@ 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)"); @@ -47,16 +66,28 @@ extern int target_flags; #define TARGET_DISABLE_FPREGS (target_flags & 2) +/* 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! */ +#define TARGET_FAST_INDIRECT_CALLS (target_flags & 4) + /* Allow unconditional jumps in the delay slots of call instructions. */ #define TARGET_JUMP_IN_DELAY (target_flags & 8) -/* Force all function calls to indirect addressing via a register. This - avoids lossage when the function is very far away from the current PC. +/* In rare cases, a millicode call via "bl" can not be turned into + a millicode call using "ble" (when SHLIB_INFO subspace is very large). + + This option forces just millicode calls to use inline long-calls + This is far more efficient than the old long-call option which forced + every function to be called indirectly (as is still the case for + TARGET_PORTABLE_RUNTIME). ??? What about simple jumps, they can suffer from the same problem. Would require significant surgery in pa.md. */ -#define TARGET_LONG_CALLS (target_flags & 16) +#define TARGET_MILLICODE_LONG_CALLS (target_flags & 16) /* Disable indexed addressing modes. */ @@ -66,7 +97,8 @@ extern int target_flags; 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) @@ -76,6 +108,10 @@ extern int target_flags; #define TARGET_GAS (target_flags & 128) +/* Emit code for processors which do not have an FPU. */ + +#define TARGET_SOFT_FLOAT (target_flags & 256) + /* Macro to define tables used to set the flags. This is a list in braces of pairs in braces, each pair being { "NAME", VALUE } @@ -88,28 +124,39 @@ extern int target_flags; {"pa-risc-1-0", -1}, \ {"pa-risc-1-1", 1}, \ {"disable-fpregs", 2}, \ - {"no-disable-fpregs", 2}, \ + {"no-disable-fpregs", -2}, \ + {"fast-indirect-calls", 4}, \ + {"no-fast-indirect-calls", -4},\ {"jump-in-delay", 8}, \ {"no-jump-in-delay", -8}, \ - {"long-calls", 16}, \ - {"no-long-calls", -16}, \ + {"millicode-long-calls", 16},\ + {"no-millicode-long-calls", -16},\ {"disable-indexing", 32}, \ {"no-disable-indexing", -32},\ {"portable-runtime", 64+16},\ {"no-portable-runtime", -(64+16)},\ {"gas", 128}, \ {"no-gas", -128}, \ + {"soft-float", 256}, \ + {"no-soft-float", -256}, \ { "", TARGET_DEFAULT}} #ifndef TARGET_DEFAULT #define TARGET_DEFAULT 0x88 /* TARGET_GAS + TARGET_JUMP_IN_DELAY */ #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. @@ -134,7 +181,7 @@ extern int target_flags; 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" @@ -159,18 +206,31 @@ extern int target_flags; ((GET_CODE (X) == PLUS ? OFFSET : 0) \ + (frame_pointer_needed ? 0 : compute_frame_size (get_frame_size (), 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) \ + fprintf (FILE, \ + "%s\n\t.stabs \"%s\",%d,0,0,L$text_end\nL$text_end:\n",\ + TEXT_SECTION_ASM_OP, "" , N_SO) + #if (TARGET_DEFAULT & 1) == 0 #define CPP_SPEC "%{msnake:-D__hp9000s700 -D_PA_RISC1_1}\ %{mpa-risc-1-1:-D__hp9000s700 -D_PA_RISC1_1}" #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}}}" #endif /* Defines for a K&R CC */ #define CC1_SPEC "%{pg:} %{p:}" -#define LINK_SPEC "-u main" +#define LINK_SPEC "%{!shared:-u main} %{shared:-b}" + +/* We don't want -lg. */ +#ifndef LIB_SPEC +#define LIB_SPEC "%{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p}" +#endif /* Allow $ in identifiers. */ #define DOLLARS_IN_IDENTIFIERS 2 @@ -182,30 +242,49 @@ extern int target_flags; #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)" + +/* 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". */ +#define PARSE_LDD_OUTPUT(PTR) \ +do { \ + while (*PTR == ' ') PTR++; \ + if (strncmp (PTR, "dynamic", sizeof ("dynamic") - 1) == 0) \ + { \ + PTR += sizeof ("dynamic") - 1; \ + while (*p == ' ') PTR++; \ + } \ + else \ + PTR = 0; \ +} while (0) /* 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 @@ -216,8 +295,6 @@ extern int target_flags; /* 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 */ @@ -322,7 +399,7 @@ extern int target_flags; 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) @@ -388,13 +465,16 @@ extern int target_flags; 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 @@ -495,12 +575,16 @@ extern int target_flags; 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 || TREE_ADDRESSABLE (TYPE)) /* Register in which address to store a structure value is passed to a function. */ @@ -715,10 +799,11 @@ enum reg_class { NO_REGS, R1_REGS, GENER /* 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). @@ -730,26 +815,29 @@ enum reg_class { NO_REGS, R1_REGS, GENER #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)) /* Define a data type for recording info about an argument list during the scan of that argument list. This data type should @@ -826,9 +914,7 @@ struct hppa_args {int words, nargs_proto 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 @@ -860,17 +946,20 @@ struct hppa_args {int words, nargs_proto #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) \ + ? (((!current_call_is_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) \ + : (((!current_call_is_indirect \ || TARGET_PORTABLE_RUNTIME) \ - && (MODE) == SFmode) \ + && (MODE) == SFmode \ + && ! TARGET_SOFT_FLOAT) \ ? (32 + 2 * (CUM).words) \ : (27 - (CUM).words - FUNCTION_ARG_SIZE ((MODE), \ (TYPE))))))\ @@ -910,6 +999,10 @@ struct hppa_args {int words, nargs_proto #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) + extern struct rtx_def *hppa_compare_op0, *hppa_compare_op1; extern enum cmp_type hppa_branch_type; @@ -952,9 +1045,11 @@ extern enum cmp_type hppa_branch_type; 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) \ { \ @@ -969,6 +1064,11 @@ extern enum cmp_type hppa_branch_type; 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++; \ @@ -990,9 +1090,9 @@ extern enum cmp_type hppa_branch_type; for (; i < 4; i++) \ fprintf (FILE, ",ARGW%d=GR", i); \ } \ - if (TYPE_MODE (fntype) == DFmode) \ + if (TYPE_MODE (fntype) == DFmode && ! TARGET_SOFT_FLOAT) \ fprintf (FILE, ",RTNVAL=FR"); \ - else if (TYPE_MODE (fntype) == SFmode) \ + else if (TYPE_MODE (fntype) == SFmode && ! TARGET_SOFT_FLOAT) \ fprintf (FILE, ",RTNVAL=FU"); \ else if (fntype != void_type_node) \ fprintf (FILE, ",RTNVAL=GR"); \ @@ -1129,7 +1229,8 @@ extern union tree_node *current_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) /* Addressing modes, and classification of registers for them. */ @@ -1185,8 +1286,9 @@ extern union tree_node *current_function 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. @@ -1307,9 +1409,7 @@ extern union tree_node *current_function && 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)) \ @@ -1320,7 +1420,9 @@ extern union tree_node *current_function 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; \ } \ @@ -1328,21 +1430,29 @@ extern union tree_node *current_function && 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; \ } /* Try machine-dependent ways of modifying an illegitimate address @@ -1414,7 +1524,7 @@ do \ _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) @@ -1427,6 +1537,17 @@ while (0) 1 + (SYMBOL_NAME)[1] == '@'\ : (SYMBOL_NAME)[0] == '@')) +/* 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 @@ -1566,8 +1687,9 @@ while (0) #define RTX_COSTS(X,CODE,OUTER_CODE) \ case MULT: \ - return TARGET_SNAKE && ! TARGET_DISABLE_FPREGS \ - ? COSTS_N_INSNS (8) : COSTS_N_INSNS (20); \ + return (TARGET_SNAKE && ! TARGET_DISABLE_FPREGS \ + && ! TARGET_SOFT_FLOAT \ + ? COSTS_N_INSNS (8) : COSTS_N_INSNS (20)); \ case DIV: \ case UDIV: \ case MOD: \ @@ -1682,6 +1804,19 @@ do { fprintf (FILE, "\t.SPACE $PRIVATE$\ #define EXTRA_SECTIONS in_bss, in_readonly_data +/* 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 () \ @@ -1697,7 +1832,10 @@ 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; \ } \ } @@ -1761,25 +1899,18 @@ readonly_data () \ 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));\ - }\ - } 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) @@ -1819,19 +1950,18 @@ readonly_data () \ /* 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. */ @@ -1878,7 +2008,7 @@ readonly_data () \ /* 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. */ @@ -1980,7 +2110,14 @@ readonly_data () \ fprintf (FILE, "%d(0,%s)", offset, reg_names [REGNO (base)]); \ break; \ case LO_SUM: \ - fputs ("R'", FILE); \ + 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)); \ fputs ("(", FILE); \ output_operand (XEXP (addr, 0), 0); \ @@ -2017,11 +2154,9 @@ extern struct rtx_def *legitimize_pic_ad 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_0_operand", {SUBREG, REG, CONST_INT, CONST_DOUBLE}}, \ {"reg_or_cint_move_operand", {SUBREG, REG, CONST_INT}}, \ {"arith_operand", {SUBREG, REG, CONST_INT}}, \ {"arith32_operand", {SUBREG, REG, CONST_INT}}, \ @@ -2043,13 +2178,29 @@ extern struct rtx_def *hppa_save_pic_tab {"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 */ \ + {"reg_or_nonsymb_mem_operand", {SUBREG, REG, MEM}}, \ + {"move_operand", {SUBREG, REG, CONST_INT, MEM}}, \ + {"pic_label_operand", {LABEL_REF, CONST}}, \ {"function_label_operand", {SYMBOL_REF}}, \ - {"reg_or_0_or_nonsymb_mem_operand", {REG, SUBREG, CONST_INT, MEM}}, \ + {"reg_or_0_or_nonsymb_mem_operand", {SUBREG, REG, CONST_INT, \ + CONST_DOUBLE, MEM}}, \ {"div_operand", {REG, CONST_INT}}, \ - {"call_operand_address", {LABEL_REF, SYMBOL_REF, CONST_INT, \ - CONST, HIGH}}, + {"call_operand_address", {SYMBOL_REF, LABEL_REF, CONST_INT, \ + CONST_DOUBLE, CONST, HIGH}}, #endif + +/* 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)