diff options
Diffstat (limited to 'gcc/config/arm/arm.c')
-rw-r--r-- | gcc/config/arm/arm.c | 57 |
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) { |