aboutsummaryrefslogtreecommitdiff
path: root/gcc/config/pa/pa.c
diff options
context:
space:
mode:
authorJeff Law <law@gcc.gnu.org>1994-11-10 21:33:43 -0700
committerJeff Law <law@gcc.gnu.org>1994-11-10 21:33:43 -0700
commit6bb36601f1c5a8f758f29523d514f9e27ee711f8 (patch)
tree4d67fb8a4a81191e22da8cca8a7163d77653ba82 /gcc/config/pa/pa.c
parent858e1c67f7b5f471fb8d74624f7074610f43fdc6 (diff)
downloadgcc-6bb36601f1c5a8f758f29523d514f9e27ee711f8.zip
gcc-6bb36601f1c5a8f758f29523d514f9e27ee711f8.tar.gz
gcc-6bb36601f1c5a8f758f29523d514f9e27ee711f8.tar.bz2
* PA PIC support.
* pa.c (secondary_reload_class): Refine. Readonly data needs a secondary reload only during PIC generation. Loading a floating point register with a constant requires a register from R1_REGS during -fPIC code generation. (read_only_operand): Constant pool entries are no longer read only during PIC code generation. (hppa_legitimize_address): If flag_pic is nonzero, then immediately call legitimize_pic_address. (emit_move_sequence): Call legitimize_pic_address to handle constant data. Handle secondary reloads for PIC. Use pic_label_operand rather than open coding the test. Handle loading a LABEL_REF when generating PIC. (legitimzie_pic_address): Handle constant data addressing for PIC here. Fix loading of symbolic addresses for -fPIC generation. (pic_label_operand): Renamed from pic_operand. Handle any read only operand (such as constant data). Reject function addresses, Accept SYMBOL_REF with the read-only bit set. Generalize to handle (const (plus (reg) (int))). (finalize_pic): Delete unused function. (check_pic): Delete function. (pic_pc_rtx): Delete variable definition. (current_function_uses_pic_offset_table): Delete extern decl. (force_reg, validize_mem): Likewise. (output_global_address): Don't tack on "-$global$" when generating PIC code. (finalize_pic): Don't emit code for initialization of hppa_save_pic_table_rtx here. Don't claim we USE pic_offset_table_rtx at function end. * pa.h (SELECT_RTX_SECTION): Define. During PIC generation everything (in the constant pool) goes into the data space. (PRINT_OPERAND_ADDRESS): Handle CONST_INTs during PIC generation. Handle LO_SUM address during -fPIC generation. (LEGITIMATE_CONSTANT_P): Reject function labels when generating PIC code. (GO_IF_LEGITIMATE_ADDRESS): Only accept pic_reg + SYMBOL_REF for -fpic. (EXTRA_SECTION_FUNCTIONS): For -fpic, use the TEXT section for constants to avoid GAS lossage. (OVERRIDE_OPTIONS): Delete. (PIC_OFFSET_TABLE_REG_CALL_CLOBBERED): Define. (FINALIZE_PIC): Delete definition. (INIT_EXPANDERS): Define. Clear hppa_save_pic_table_rtx here. * pa.md: Use !flag_pic rather than calling check_pic. (HImode high and lo_sum): Only accept const_int_operands. (pic_load_label): Force output to be in %r1. (pic_highpart): New pattern. Output must go into %r1. More linker trickery. (symbolic high and lo_sum): Disallow during PIC generation if source is a symbolic operand. Handle CONST_INT LO_SUM during PIC generation. Simplify. (define_split for symbolic_operand load): Do not accept a symbolic operand that is a pic_label_operand. (pic_load_label): Name this pattern. Mask least significant bits and optimize when a simple label is within reach of an ldo. (call, call_value): Emit new-style USE information for pic_offset_table_rtx. Emit code for initialization of hppa_save_pic_table_rtx and wrap it into push_topmost_sequence() and pop_topmost_sequence() calls. From-SVN: r8419
Diffstat (limited to 'gcc/config/pa/pa.c')
-rw-r--r--gcc/config/pa/pa.c131
1 files changed, 65 insertions, 66 deletions
diff --git a/gcc/config/pa/pa.c b/gcc/config/pa/pa.c
index 168cf0c..2ec55ba 100644
--- a/gcc/config/pa/pa.c
+++ b/gcc/config/pa/pa.c
@@ -219,11 +219,29 @@ reg_or_cint_move_operand (op, mode)
}
int
-pic_operand (op, mode)
+pic_label_operand (op, mode)
rtx op;
enum machine_mode mode;
{
- return flag_pic && GET_CODE (op) == LABEL_REF;
+ if (!flag_pic)
+ return 0;
+
+ switch (GET_CODE (op))
+ {
+ case LABEL_REF:
+ return 1;
+ case SYMBOL_REF:
+ return (read_only_operand (op) && !FUNCTION_NAME_P (XSTR (op, 0)));
+ case CONST:
+ op = XEXP (op, 0);
+ return (((GET_CODE (XEXP (op, 0)) == SYMBOL_REF
+ && read_only_operand (XEXP (op, 0))
+ && !FUNCTION_NAME_P (XSTR (XEXP (op, 0), 0)))
+ || GET_CODE (XEXP (op, 0)) == LABEL_REF)
+ && GET_CODE (XEXP (op, 1)) == CONST_INT);
+ default:
+ return 0;
+ }
}
int
@@ -235,32 +253,6 @@ fp_reg_operand (op, mode)
}
-extern int current_function_uses_pic_offset_table;
-extern rtx force_reg (), validize_mem ();
-
-/* The rtx for the global offset table which is a special form
- that *is* a position independent symbolic constant. */
-rtx pic_pc_rtx;
-
-/* Ensure that we are not using patterns that are not OK with PIC. */
-
-int
-check_pic (i)
- int i;
-{
- extern rtx recog_operand[];
- switch (flag_pic)
- {
- case 1:
- if (GET_CODE (recog_operand[i]) == SYMBOL_REF
- || (GET_CODE (recog_operand[i]) == CONST
- && ! rtx_equal_p (pic_pc_rtx, recog_operand[i])))
- abort ();
- case 2:
- default:
- return 1;
- }
-}
/* Return truth value of whether OP can be used as an operand in a
three operand arithmetic insn that accepts registers of mode MODE
@@ -480,6 +472,13 @@ legitimize_pic_address (orig, mode, reg)
{
rtx pic_ref = orig;
+ /* Lables and read-only data need special handling. */
+ if (pic_label_operand (orig))
+ {
+ emit_insn (gen_pic_load_label (reg, orig));
+ current_function_uses_pic_offset_table = 1;
+ return reg;
+ }
if (GET_CODE (orig) == SYMBOL_REF)
{
if (reg == 0)
@@ -487,15 +486,12 @@ legitimize_pic_address (orig, mode, reg)
if (flag_pic == 2)
{
- emit_insn (gen_rtx (SET, VOIDmode, reg,
- gen_rtx (HIGH, Pmode, orig)));
- emit_insn (gen_rtx (SET, VOIDmode, reg,
- gen_rtx (LO_SUM, Pmode, reg, orig)));
- orig = reg;
+ emit_insn (gen_pic_highpart (reg, pic_offset_table_rtx, orig));
+ pic_ref = (gen_rtx (MEM, Pmode, gen_rtx (LO_SUM, Pmode, reg, orig)));
}
- pic_ref = gen_rtx (MEM, Pmode,
- gen_rtx (PLUS, Pmode,
- pic_offset_table_rtx, orig));
+ else
+ pic_ref = gen_rtx (MEM, Pmode,
+ gen_rtx (PLUS, Pmode, pic_offset_table_rtx, orig));
current_function_uses_pic_offset_table = 1;
RTX_UNCHANGING_P (pic_ref) = 1;
emit_move_insn (reg, pic_ref);
@@ -531,24 +527,6 @@ legitimize_pic_address (orig, mode, reg)
return pic_ref;
}
-/* Emit special PIC prologues and epilogues. */
-
-void
-finalize_pic ()
-{
- if (hppa_save_pic_table_rtx)
- {
- emit_insn_after (gen_rtx (SET, VOIDmode,
- hppa_save_pic_table_rtx,
- gen_rtx (REG, Pmode, PIC_OFFSET_TABLE_REGNUM)),
- get_insns ());
- /* Need to emit this whether or not we obey regdecls,
- since setjmp/longjmp can cause life info to screw up. */
- hppa_save_pic_table_rtx = 0;
- }
- emit_insn (gen_rtx (USE, VOIDmode, pic_offset_table_rtx));
-}
-
/* Try machine-dependent ways of modifying an illegitimate address
to be legitimate. If we find one, return the new, valid address.
This macro is used in only one place: `memory_address' in explow.c.
@@ -607,6 +585,9 @@ hppa_legitimize_address (x, oldx, mode)
{
rtx orig = x;
+ if (flag_pic)
+ return legitimize_pic_address (x, mode, gen_reg_rtx (Pmode));
+
/* Strip off CONST. */
if (GET_CODE (x) == CONST)
x = XEXP (x, 0);
@@ -727,9 +708,6 @@ hppa_legitimize_address (x, oldx, mode)
}
}
- if (flag_pic)
- return legitimize_pic_address (x, mode, gen_reg_rtx (Pmode));
-
return orig;
}
@@ -895,16 +873,16 @@ emit_move_sequence (operands, mode, scratch_reg)
rtx temp;
if (reload_in_progress || reload_completed)
- temp = operand0;
+ temp = scratch_reg ? scratch_reg : operand0;
else
temp = gen_reg_rtx (Pmode);
operands[1] = legitimize_pic_address (operand1, mode, temp);
- emit_insn (gen_rtx (SET, VOIDmode, operand0, operands[1]));
+ emit_insn (gen_rtx (SET, VOIDmode, operand0, operands[1]));
}
- /* On the HPPA, references to data space are supposed to */
- /* use dp, register 27, but showing it in the RTL inhibits various
- cse and loop optimizations. */
+ /* On the HPPA, references to data space are supposed to use dp,
+ register 27, but showing it in the RTL inhibits various cse
+ and loop optimizations. */
else
{
rtx temp, set, const_part = NULL;
@@ -982,8 +960,16 @@ read_only_operand (operand)
{
if (GET_CODE (operand) == CONST)
operand = XEXP (XEXP (operand, 0), 0);
- if (GET_CODE (operand) == SYMBOL_REF)
- return SYMBOL_REF_FLAG (operand) || CONSTANT_POOL_ADDRESS_P (operand);
+ if (flag_pic)
+ {
+ if (GET_CODE (operand) == SYMBOL_REF)
+ return SYMBOL_REF_FLAG (operand) && !CONSTANT_POOL_ADDRESS_P (operand);
+ }
+ else
+ {
+ if (GET_CODE (operand) == SYMBOL_REF)
+ return SYMBOL_REF_FLAG (operand) || CONSTANT_POOL_ADDRESS_P (operand);
+ }
return 1;
}
@@ -2950,7 +2936,7 @@ output_global_address (file, x)
if (GET_CODE (x) == SYMBOL_REF && read_only_operand (x))
assemble_name (file, XSTR (x, 0));
- else if (GET_CODE (x) == SYMBOL_REF)
+ else if (GET_CODE (x) == SYMBOL_REF && !flag_pic)
{
assemble_name (file, XSTR (x, 0));
fprintf (file, "-$global$");
@@ -2994,7 +2980,7 @@ output_global_address (file, x)
sep = "-";
else abort ();
- if (!read_only_operand (base))
+ if (!read_only_operand (base) && !flag_pic)
fprintf (file, "-$global$");
fprintf (file, "%s", sep);
if (offset) fprintf (file,"%d", offset);
@@ -3261,6 +3247,14 @@ secondary_reload_class (class, mode, in)
{
int regno = true_regnum (in);
+ /* Trying to load a constant into a FP register during PIC code
+ generation will require %r1 as a scratch register. */
+ if (flag_pic == 2
+ && GET_MODE_CLASS (mode) == MODE_INT
+ && FP_REG_CLASS_P (class)
+ && (GET_CODE (in) == CONST_INT || GET_CODE (in) == CONST_DOUBLE))
+ return R1_REGS;
+
if (((regno >= FIRST_PSEUDO_REGISTER || regno == -1)
&& GET_MODE_CLASS (mode) == MODE_INT
&& FP_REG_CLASS_P (class))
@@ -3270,6 +3264,11 @@ secondary_reload_class (class, mode, in)
if (GET_CODE (in) == HIGH)
in = XEXP (in, 0);
+ if (!flag_pic
+ && symbolic_operand (in, VOIDmode)
+ && read_only_operand (in))
+ return NO_REGS;
+
if (class != R1_REGS && symbolic_operand (in, VOIDmode))
return R1_REGS;