aboutsummaryrefslogtreecommitdiff
path: root/gcc/config/arm/arm.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/config/arm/arm.c')
-rw-r--r--gcc/config/arm/arm.c57
1 files changed, 40 insertions, 17 deletions
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index e2fe037ad56..553e25c7b76 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -70,6 +70,9 @@ static void emit_sfm PROTO ((int, int));
static enum arm_cond_code get_arm_condition_code PROTO ((rtx));
static int const_ok_for_op RTX_CODE_PROTO ((Hint, Rcode));
+/* True if we are currently building a constant table. */
+int making_const_table;
+
/* Define the information needed to generate branch insns. This is
stored from the compare operation. */
rtx arm_compare_op0, arm_compare_op1;
@@ -483,13 +486,6 @@ arm_override_options ()
if (flag_pic && ! TARGET_APCS_STACK)
arm_pic_register = 10;
- /* Well, I'm about to have a go, but pic is NOT going to be compatible
- with APCS reentrancy, since that requires too much support in the
- assembler and linker, and the ARMASM assembler seems to lack some
- required directives. */
- if (flag_pic)
- warning ("Position independent code not supported");
-
if (TARGET_APCS_FLOAT)
warning ("Passing floating point arguments in fp regs not yet supported");
@@ -580,9 +576,14 @@ use_return_insn (iscond)
return 0;
if ((iscond && arm_is_strong)
|| TARGET_THUMB_INTERWORK)
- for (regno = 0; regno < 16; regno++)
- if (regs_ever_live[regno] && ! call_used_regs[regno])
+ {
+ for (regno = 0; regno < 16; regno++)
+ if (regs_ever_live[regno] && ! call_used_regs[regno])
+ return 0;
+
+ if (flag_pic && regs_ever_live[PIC_OFFSET_TABLE_REGNUM])
return 0;
+ }
/* Can't be done if any of the FPU regs are pushed, since this also
requires an insn */
@@ -1563,8 +1564,11 @@ arm_finalize_pic ()
/* On the ARM the PC register contains 'dot + 8' at the time of the
addition. */
pic_tmp = plus_constant (gen_rtx_LABEL_REF (Pmode, l1), 8);
- pic_tmp2 = gen_rtx_CONST (VOIDmode,
+ if (GOT_PCREL)
+ pic_tmp2 = gen_rtx_CONST (VOIDmode,
gen_rtx_PLUS (Pmode, global_offset_table, pc_rtx));
+ else
+ pic_tmp2 = gen_rtx_CONST (VOIDmode, global_offset_table);
pic_rtx = gen_rtx_CONST (Pmode, gen_rtx_MINUS (Pmode, pic_tmp2, pic_tmp));
@@ -3698,7 +3702,7 @@ arm_reload_in_hi (operands)
gen_rtx_MEM (QImode,
plus_constant (base,
offset + 1))));
- if (BYTES_BIG_ENDIAN)
+ if (! BYTES_BIG_ENDIAN)
emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_SUBREG (SImode, operands[0], 0),
gen_rtx_IOR (SImode,
gen_rtx_ASHIFT
@@ -5313,6 +5317,9 @@ output_return_instruction (operand, really_return, reverse)
if (regs_ever_live[reg] && ! call_used_regs[reg])
live_regs++;
+ if (flag_pic && regs_ever_live[PIC_OFFSET_TABLE_REGNUM])
+ live_regs++;
+
if (live_regs || (regs_ever_live[14] && ! lr_save_eliminated))
live_regs++;
@@ -5332,7 +5339,9 @@ output_return_instruction (operand, really_return, reverse)
reverse ? "ldm%?%D0fd\t%|sp!, {" : "ldm%?%d0fd\t%|sp!, {");
for (reg = 0; reg <= 10; reg++)
- if (regs_ever_live[reg] && ! call_used_regs[reg])
+ if (regs_ever_live[reg]
+ && (! call_used_regs[reg]
+ || (flag_pic && reg == PIC_OFFSET_TABLE_REGNUM)))
{
strcat (instr, "%|");
strcat (instr, reg_names[reg]);
@@ -5492,6 +5501,9 @@ output_func_prologue (f, frame_size)
if (regs_ever_live[reg] && ! call_used_regs[reg])
live_regs_mask |= (1 << reg);
+ if (flag_pic && regs_ever_live[PIC_OFFSET_TABLE_REGNUM])
+ live_regs_mask |= (1 << PIC_OFFSET_TABLE_REGNUM);
+
if (frame_pointer_needed)
live_regs_mask |= 0xD800;
else if (regs_ever_live[14])
@@ -5568,6 +5580,12 @@ output_func_epilogue (f, frame_size)
floats_offset += 4;
}
+ if (flag_pic && regs_ever_live[PIC_OFFSET_TABLE_REGNUM])
+ {
+ live_regs_mask |= (1 << PIC_OFFSET_TABLE_REGNUM);
+ floats_offset += 4;
+ }
+
if (frame_pointer_needed)
{
if (arm_fpu_arch == FP_SOFT2)
@@ -5828,12 +5846,17 @@ arm_expand_prologue ()
store_arg_regs = 1;
if (! volatile_func)
- for (reg = 0; reg <= 10; reg++)
- if (regs_ever_live[reg] && ! call_used_regs[reg])
- live_regs_mask |= 1 << reg;
+ {
+ for (reg = 0; reg <= 10; reg++)
+ if (regs_ever_live[reg] && ! call_used_regs[reg])
+ live_regs_mask |= 1 << reg;
- if (! volatile_func && regs_ever_live[14])
- live_regs_mask |= 0x4000;
+ if (flag_pic && regs_ever_live[PIC_OFFSET_TABLE_REGNUM])
+ live_regs_mask |= 1 << PIC_OFFSET_TABLE_REGNUM;
+
+ if (regs_ever_live[14])
+ live_regs_mask |= 0x4000;
+ }
if (frame_pointer_needed)
{