config.gcc (arm-wrs-vxworks): Remove dbxelf.h from tm_file.
gcc/ * config.gcc (arm-wrs-vxworks): Remove dbxelf.h from tm_file. Add vx-common.h. Include vxworks.h between vx-common.h and arm/vxworks.h. * config/vx-common.h (DWARF2_UNWIND_INFO): Undefine before redefining. * config/vxworks.h (TARGET_ASM_CONSTRUCTOR): Likewise. (TARGET_ASM_DESTRUCTOR): Likewise. * config/arm/vxworks.h (TARGET_OS_CPP_BUILTINS): Check arm_arch_xscale instead of arm_is_xscale. Use VXWORKS_OS_CPP_BUILTINS. (OVERRIDE_OPTIONS, SUBTARGET_CPP_SPEC): Define. (CC1_SPEC): Add -tstrongarm. Line up backslashes. (VXWORKS_ENDIAN_SPEC): Define. (ASM_SPEC): Add VXWORKS_ENDIAN_SPEC. (LIB_SPEC, STARTFILE_SPEC, ENDFILE_SPEC): Redefine to their VXWORKS_* equivalents. (LINK_SPEC): Likewise, but add VXWORKS_ENDIAN_SPEC. (ASM_FILE_START): Delete. (TARGET_VERSION): Reformat. (FPUTYPE_DEFAULT, FUNCTION_PROFILER): Define. (DEFAULT_STRUCTURE_SIZE_BOUNDARY): Define. * config/arm/t-vxworks (LIB1ASMSRC, LIB1ASMFUNCS): Define. (FPBIT, DPBIT): Define. (fp-bit.c, dp-bit.c): New rules. (MULTILIB_OPTIONS): Add strongarm, -mrtp and -mrtp/-fPIC multilibs. (MULTILIB_MATCHES, MULTILIB_EXCEPTIONS): Define. * config/arm/arm-protos.h (arm_emit_call_insn): Declare. * config/arm/arm.h: Include vxworks-dummy.h. * config/arm/arm.c (arm_elf_asm_constructor, arm_elf_asm_destructor): Mark with ATTRIBUTE_UNUSED. (arm_override_options): Do not allow VxWorks RTP PIC to be used for Thumb. Force r9 to be the PIC register for VxWorks RTPs and make it incompatible with -msingle-pic-base. (arm_function_ok_for_sibcall): Return false for calls that might go through a VxWorks PIC PLT entry. (require_pic_register): New function, split out from... (legitimize_pic_address): ...here. Do not use GOTOFF accesses for VxWorks RTPs. (arm_load_pic_register): Handle the VxWorks RTP initialization sequence. Use pic_reg as a shorthand for cfun->machine->pic_reg. (arm_emit_call_insn): New function. (arm_assemble_integer): Do not use GOTOFF accesses for VxWorks RTP. * config/arm/arm.md (UNSPEC_PIC_OFFSET): New unspec number. (pic_offset_arm): New pattern. (call, call_value): Use arm_emit_call_insn. (call_internal, call_value_internal): New expanders. * config/arm/lib1funcs.asm (__PLT__): Define to empty for VxWorks unless __PIC__. From-SVN: r125196
This commit is contained in:
parent
f52ae0770f
commit
9403b7f7ca
11 changed files with 347 additions and 149 deletions
|
@ -1,3 +1,53 @@
|
|||
2007-05-30 Richard Sandiford <richard@codesourcery.com>
|
||||
|
||||
* config.gcc (arm-wrs-vxworks): Remove dbxelf.h from tm_file.
|
||||
Add vx-common.h. Include vxworks.h between vx-common.h and
|
||||
arm/vxworks.h.
|
||||
* config/vx-common.h (DWARF2_UNWIND_INFO): Undefine before
|
||||
redefining.
|
||||
* config/vxworks.h (TARGET_ASM_CONSTRUCTOR): Likewise.
|
||||
(TARGET_ASM_DESTRUCTOR): Likewise.
|
||||
* config/arm/vxworks.h (TARGET_OS_CPP_BUILTINS): Check arm_arch_xscale
|
||||
instead of arm_is_xscale. Use VXWORKS_OS_CPP_BUILTINS.
|
||||
(OVERRIDE_OPTIONS, SUBTARGET_CPP_SPEC): Define.
|
||||
(CC1_SPEC): Add -tstrongarm. Line up backslashes.
|
||||
(VXWORKS_ENDIAN_SPEC): Define.
|
||||
(ASM_SPEC): Add VXWORKS_ENDIAN_SPEC.
|
||||
(LIB_SPEC, STARTFILE_SPEC, ENDFILE_SPEC): Redefine to their
|
||||
VXWORKS_* equivalents.
|
||||
(LINK_SPEC): Likewise, but add VXWORKS_ENDIAN_SPEC.
|
||||
(ASM_FILE_START): Delete.
|
||||
(TARGET_VERSION): Reformat.
|
||||
(FPUTYPE_DEFAULT, FUNCTION_PROFILER): Define.
|
||||
(DEFAULT_STRUCTURE_SIZE_BOUNDARY): Define.
|
||||
* config/arm/t-vxworks (LIB1ASMSRC, LIB1ASMFUNCS): Define.
|
||||
(FPBIT, DPBIT): Define.
|
||||
(fp-bit.c, dp-bit.c): New rules.
|
||||
(MULTILIB_OPTIONS): Add strongarm, -mrtp and -mrtp/-fPIC multilibs.
|
||||
(MULTILIB_MATCHES, MULTILIB_EXCEPTIONS): Define.
|
||||
* config/arm/arm-protos.h (arm_emit_call_insn): Declare.
|
||||
* config/arm/arm.h: Include vxworks-dummy.h.
|
||||
* config/arm/arm.c (arm_elf_asm_constructor, arm_elf_asm_destructor):
|
||||
Mark with ATTRIBUTE_UNUSED.
|
||||
(arm_override_options): Do not allow VxWorks RTP PIC to be used
|
||||
for Thumb. Force r9 to be the PIC register for VxWorks RTPs and
|
||||
make it incompatible with -msingle-pic-base.
|
||||
(arm_function_ok_for_sibcall): Return false for calls that might
|
||||
go through a VxWorks PIC PLT entry.
|
||||
(require_pic_register): New function, split out from...
|
||||
(legitimize_pic_address): ...here. Do not use GOTOFF accesses
|
||||
for VxWorks RTPs.
|
||||
(arm_load_pic_register): Handle the VxWorks RTP initialization
|
||||
sequence. Use pic_reg as a shorthand for cfun->machine->pic_reg.
|
||||
(arm_emit_call_insn): New function.
|
||||
(arm_assemble_integer): Do not use GOTOFF accesses for VxWorks RTP.
|
||||
* config/arm/arm.md (UNSPEC_PIC_OFFSET): New unspec number.
|
||||
(pic_offset_arm): New pattern.
|
||||
(call, call_value): Use arm_emit_call_insn.
|
||||
(call_internal, call_value_internal): New expanders.
|
||||
* config/arm/lib1funcs.asm (__PLT__): Define to empty for
|
||||
VxWorks unless __PIC__.
|
||||
|
||||
2007-05-30 Eric Christopher <echristo@gmail.com>
|
||||
|
||||
* genrecog.c: Include regs.h in generated file.
|
||||
|
|
|
@ -697,7 +697,7 @@ arm-semi-aof | armel-semi-aof)
|
|||
tmake_file="arm/t-arm arm/t-semi"
|
||||
;;
|
||||
arm-wrs-vxworks)
|
||||
tm_file="dbxelf.h elfos.h svr4.h vxworks.h arm/elf.h arm/aout.h ${tm_file} arm/vxworks.h"
|
||||
tm_file="elfos.h svr4.h arm/elf.h arm/aout.h ${tm_file} vx-common.h vxworks.h arm/vxworks.h"
|
||||
tmake_file="${tmake_file} arm/t-arm arm/t-vxworks"
|
||||
;;
|
||||
arm*-*-freebsd*|strongarm*-*-freebsd*)
|
||||
|
|
|
@ -102,6 +102,7 @@ extern void arm_reload_out_hi (rtx *);
|
|||
extern int arm_const_double_inline_cost (rtx);
|
||||
extern bool arm_const_double_by_parts (rtx);
|
||||
extern const char *fp_immediate_constant (rtx);
|
||||
extern void arm_emit_call_insn (rtx, rtx);
|
||||
extern const char *output_call (rtx *);
|
||||
extern const char *output_call_mem (rtx *);
|
||||
extern const char *output_mov_long_double_fpa_from_arm (rtx *);
|
||||
|
|
|
@ -148,8 +148,8 @@ static int arm_arg_partial_bytes (CUMULATIVE_ARGS *, enum machine_mode,
|
|||
tree, bool);
|
||||
|
||||
#ifdef OBJECT_FORMAT_ELF
|
||||
static void arm_elf_asm_constructor (rtx, int);
|
||||
static void arm_elf_asm_destructor (rtx, int);
|
||||
static void arm_elf_asm_constructor (rtx, int) ATTRIBUTE_UNUSED;
|
||||
static void arm_elf_asm_destructor (rtx, int) ATTRIBUTE_UNUSED;
|
||||
#endif
|
||||
#ifndef ARM_PE
|
||||
static void arm_encode_section_info (tree, rtx, int);
|
||||
|
@ -1338,10 +1338,23 @@ arm_override_options (void)
|
|||
ARM_DOUBLEWORD_ALIGN ? "8, 32 or 64": "8 or 32");
|
||||
}
|
||||
|
||||
if (!TARGET_ARM && TARGET_VXWORKS_RTP && flag_pic)
|
||||
{
|
||||
error ("RTP PIC is incompatible with Thumb");
|
||||
flag_pic = 0;
|
||||
}
|
||||
|
||||
/* If stack checking is disabled, we can use r10 as the PIC register,
|
||||
which keeps r9 available. The EABI specifies r9 as the PIC register. */
|
||||
if (flag_pic && TARGET_SINGLE_PIC_BASE)
|
||||
arm_pic_register = (TARGET_APCS_STACK || TARGET_AAPCS_BASED) ? 9 : 10;
|
||||
{
|
||||
if (TARGET_VXWORKS_RTP)
|
||||
warning (0, "RTP PIC is incompatible with -msingle-pic-base");
|
||||
arm_pic_register = (TARGET_APCS_STACK || TARGET_AAPCS_BASED) ? 9 : 10;
|
||||
}
|
||||
|
||||
if (flag_pic && TARGET_VXWORKS_RTP)
|
||||
arm_pic_register = 9;
|
||||
|
||||
if (arm_pic_register_string != NULL)
|
||||
{
|
||||
|
@ -1354,7 +1367,9 @@ arm_override_options (void)
|
|||
else if (pic_register < 0 || call_used_regs[pic_register]
|
||||
|| pic_register == HARD_FRAME_POINTER_REGNUM
|
||||
|| pic_register == STACK_POINTER_REGNUM
|
||||
|| pic_register >= PC_REGNUM)
|
||||
|| pic_register >= PC_REGNUM
|
||||
|| (TARGET_VXWORKS_RTP
|
||||
&& (unsigned int) pic_register != arm_pic_register))
|
||||
error ("unable to use '%s' for PIC register", arm_pic_register_string);
|
||||
else
|
||||
arm_pic_register = pic_register;
|
||||
|
@ -3214,6 +3229,11 @@ arm_function_ok_for_sibcall (tree decl, tree exp ATTRIBUTE_UNUSED)
|
|||
if (decl == NULL || TARGET_THUMB)
|
||||
return false;
|
||||
|
||||
/* The PIC register is live on entry to VxWorks PLT entries, so we
|
||||
must make the call before restoring the PIC register. */
|
||||
if (TARGET_VXWORKS_RTP && flag_pic && !targetm.binds_local_p (decl))
|
||||
return false;
|
||||
|
||||
/* Cannot tail-call to long calls, since these are out of range of
|
||||
a branch instruction. */
|
||||
if (arm_is_long_call_p (decl))
|
||||
|
@ -3255,6 +3275,54 @@ legitimate_pic_operand_p (rtx x)
|
|||
return 1;
|
||||
}
|
||||
|
||||
/* Record that the current function needs a PIC register. Initialize
|
||||
cfun->machine->pic_reg if we have not already done so. */
|
||||
|
||||
static void
|
||||
require_pic_register (void)
|
||||
{
|
||||
/* A lot of the logic here is made obscure by the fact that this
|
||||
routine gets called as part of the rtx cost estimation process.
|
||||
We don't want those calls to affect any assumptions about the real
|
||||
function; and further, we can't call entry_of_function() until we
|
||||
start the real expansion process. */
|
||||
if (!current_function_uses_pic_offset_table)
|
||||
{
|
||||
gcc_assert (!no_new_pseudos);
|
||||
if (arm_pic_register != INVALID_REGNUM)
|
||||
{
|
||||
cfun->machine->pic_reg = gen_rtx_REG (Pmode, arm_pic_register);
|
||||
|
||||
/* Play games to avoid marking the function as needing pic
|
||||
if we are being called as part of the cost-estimation
|
||||
process. */
|
||||
if (current_ir_type () != IR_GIMPLE)
|
||||
current_function_uses_pic_offset_table = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
rtx seq;
|
||||
|
||||
cfun->machine->pic_reg = gen_reg_rtx (Pmode);
|
||||
|
||||
/* Play games to avoid marking the function as needing pic
|
||||
if we are being called as part of the cost-estimation
|
||||
process. */
|
||||
if (current_ir_type () != IR_GIMPLE)
|
||||
{
|
||||
current_function_uses_pic_offset_table = 1;
|
||||
start_sequence ();
|
||||
|
||||
arm_load_pic_register (0UL);
|
||||
|
||||
seq = get_insns ();
|
||||
end_sequence ();
|
||||
emit_insn_after (seq, entry_of_function ());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rtx
|
||||
legitimize_pic_address (rtx orig, enum machine_mode mode, rtx reg)
|
||||
{
|
||||
|
@ -3267,48 +3335,8 @@ legitimize_pic_address (rtx orig, enum machine_mode mode, rtx reg)
|
|||
rtx insn;
|
||||
int subregs = 0;
|
||||
|
||||
/* If this function doesn't have a pic register, create one now.
|
||||
A lot of the logic here is made obscure by the fact that this
|
||||
routine gets called as part of the rtx cost estimation
|
||||
process. We don't want those calls to affect any assumptions
|
||||
about the real function; and further, we can't call
|
||||
entry_of_function() until we start the real expansion
|
||||
process. */
|
||||
if (!current_function_uses_pic_offset_table)
|
||||
{
|
||||
gcc_assert (!no_new_pseudos);
|
||||
if (arm_pic_register != INVALID_REGNUM)
|
||||
{
|
||||
cfun->machine->pic_reg = gen_rtx_REG (Pmode, arm_pic_register);
|
||||
|
||||
/* Play games to avoid marking the function as needing pic
|
||||
if we are being called as part of the cost-estimation
|
||||
process. */
|
||||
if (current_ir_type () != IR_GIMPLE)
|
||||
current_function_uses_pic_offset_table = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
rtx seq;
|
||||
|
||||
cfun->machine->pic_reg = gen_reg_rtx (Pmode);
|
||||
|
||||
/* Play games to avoid marking the function as needing pic
|
||||
if we are being called as part of the cost-estimation
|
||||
process. */
|
||||
if (current_ir_type () != IR_GIMPLE)
|
||||
{
|
||||
current_function_uses_pic_offset_table = 1;
|
||||
start_sequence ();
|
||||
|
||||
arm_load_pic_register (0UL);
|
||||
|
||||
seq = get_insns ();
|
||||
end_sequence ();
|
||||
emit_insn_after (seq, entry_of_function ());
|
||||
}
|
||||
}
|
||||
}
|
||||
/* If this function doesn't have a pic register, create one now. */
|
||||
require_pic_register ();
|
||||
|
||||
if (reg == 0)
|
||||
{
|
||||
|
@ -3335,10 +3363,17 @@ legitimize_pic_address (rtx orig, enum machine_mode mode, rtx reg)
|
|||
else /* TARGET_THUMB1 */
|
||||
emit_insn (gen_pic_load_addr_thumb1 (address, orig));
|
||||
|
||||
/* VxWorks does not impose a fixed gap between segments; the run-time
|
||||
gap can be different from the object-file gap. We therefore can't
|
||||
use GOTOFF unless we are absolutely sure that the symbol is in the
|
||||
same segment as the GOT. Unfortunately, the flexibility of linker
|
||||
scripts means that we can't be sure of that in general, so assume
|
||||
that GOTOFF is never valid on VxWorks. */
|
||||
if ((GET_CODE (orig) == LABEL_REF
|
||||
|| (GET_CODE (orig) == SYMBOL_REF &&
|
||||
SYMBOL_REF_LOCAL_P (orig)))
|
||||
&& NEED_GOT_RELOC)
|
||||
&& NEED_GOT_RELOC
|
||||
&& !TARGET_VXWORKS_RTP)
|
||||
pic_ref = gen_rtx_PLUS (Pmode, cfun->machine->pic_reg, address);
|
||||
else
|
||||
{
|
||||
|
@ -3478,7 +3513,7 @@ void
|
|||
arm_load_pic_register (unsigned long saved_regs ATTRIBUTE_UNUSED)
|
||||
{
|
||||
#ifndef AOF_ASSEMBLER
|
||||
rtx l1, labelno, pic_tmp, pic_tmp2, pic_rtx;
|
||||
rtx l1, labelno, pic_tmp, pic_tmp2, pic_rtx, pic_reg;
|
||||
rtx global_offset_table;
|
||||
|
||||
if (current_function_uses_pic_offset_table == 0 || TARGET_SINGLE_PIC_BASE)
|
||||
|
@ -3486,72 +3521,88 @@ arm_load_pic_register (unsigned long saved_regs ATTRIBUTE_UNUSED)
|
|||
|
||||
gcc_assert (flag_pic);
|
||||
|
||||
/* We use an UNSPEC rather than a LABEL_REF because this label never appears
|
||||
in the code stream. */
|
||||
pic_reg = cfun->machine->pic_reg;
|
||||
if (TARGET_VXWORKS_RTP)
|
||||
{
|
||||
pic_rtx = gen_rtx_SYMBOL_REF (Pmode, VXWORKS_GOTT_BASE);
|
||||
pic_rtx = gen_rtx_CONST (Pmode, pic_rtx);
|
||||
emit_insn (gen_pic_load_addr_arm (pic_reg, pic_rtx));
|
||||
|
||||
labelno = GEN_INT (pic_labelno++);
|
||||
l1 = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, labelno), UNSPEC_PIC_LABEL);
|
||||
l1 = gen_rtx_CONST (VOIDmode, l1);
|
||||
emit_insn (gen_rtx_SET (Pmode, pic_reg, gen_rtx_MEM (Pmode, pic_reg)));
|
||||
|
||||
global_offset_table = gen_rtx_SYMBOL_REF (Pmode, "_GLOBAL_OFFSET_TABLE_");
|
||||
/* On the ARM the PC register contains 'dot + 8' at the time of the
|
||||
addition, on the Thumb it is 'dot + 4'. */
|
||||
pic_tmp = plus_constant (l1, TARGET_ARM ? 8 : 4);
|
||||
if (GOT_PCREL)
|
||||
pic_tmp2 = gen_rtx_CONST (VOIDmode,
|
||||
gen_rtx_PLUS (Pmode, global_offset_table, pc_rtx));
|
||||
pic_tmp = gen_rtx_SYMBOL_REF (Pmode, VXWORKS_GOTT_INDEX);
|
||||
emit_insn (gen_pic_offset_arm (pic_reg, pic_reg, pic_tmp));
|
||||
}
|
||||
else
|
||||
pic_tmp2 = gen_rtx_CONST (VOIDmode, global_offset_table);
|
||||
|
||||
pic_rtx = gen_rtx_CONST (Pmode, gen_rtx_MINUS (Pmode, pic_tmp2, pic_tmp));
|
||||
|
||||
if (TARGET_ARM)
|
||||
{
|
||||
emit_insn (gen_pic_load_addr_arm (cfun->machine->pic_reg, pic_rtx));
|
||||
emit_insn (gen_pic_add_dot_plus_eight (cfun->machine->pic_reg,
|
||||
cfun->machine->pic_reg, labelno));
|
||||
}
|
||||
else if (TARGET_THUMB2)
|
||||
{
|
||||
/* Thumb-2 only allows very limited access to the PC. Calculate the
|
||||
address in a temporary register. */
|
||||
if (arm_pic_register != INVALID_REGNUM)
|
||||
/* We use an UNSPEC rather than a LABEL_REF because this label
|
||||
never appears in the code stream. */
|
||||
|
||||
labelno = GEN_INT (pic_labelno++);
|
||||
l1 = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, labelno), UNSPEC_PIC_LABEL);
|
||||
l1 = gen_rtx_CONST (VOIDmode, l1);
|
||||
|
||||
global_offset_table
|
||||
= gen_rtx_SYMBOL_REF (Pmode, "_GLOBAL_OFFSET_TABLE_");
|
||||
/* On the ARM the PC register contains 'dot + 8' at the time of the
|
||||
addition, on the Thumb it is 'dot + 4'. */
|
||||
pic_tmp = plus_constant (l1, TARGET_ARM ? 8 : 4);
|
||||
if (GOT_PCREL)
|
||||
{
|
||||
pic_tmp = gen_rtx_REG (SImode,
|
||||
thumb_find_work_register (saved_regs));
|
||||
pic_tmp2 = gen_rtx_PLUS (Pmode, global_offset_table, pc_rtx);
|
||||
pic_tmp2 = gen_rtx_CONST (VOIDmode, pic_tmp2);
|
||||
}
|
||||
else
|
||||
{
|
||||
gcc_assert (!no_new_pseudos);
|
||||
pic_tmp = gen_reg_rtx (Pmode);
|
||||
}
|
||||
pic_tmp2 = gen_rtx_CONST (VOIDmode, global_offset_table);
|
||||
|
||||
emit_insn (gen_pic_load_addr_thumb2 (cfun->machine->pic_reg, pic_rtx));
|
||||
emit_insn (gen_pic_load_dot_plus_four (pic_tmp, labelno));
|
||||
emit_insn (gen_addsi3(cfun->machine->pic_reg, cfun->machine->pic_reg,
|
||||
pic_tmp));
|
||||
}
|
||||
else /* TARGET_THUMB1 */
|
||||
{
|
||||
if (arm_pic_register != INVALID_REGNUM
|
||||
&& REGNO (cfun->machine->pic_reg) > LAST_LO_REGNUM)
|
||||
pic_rtx = gen_rtx_MINUS (Pmode, pic_tmp2, pic_tmp);
|
||||
pic_rtx = gen_rtx_CONST (Pmode, pic_rtx);
|
||||
|
||||
if (TARGET_ARM)
|
||||
{
|
||||
/* We will have pushed the pic register, so we should always be
|
||||
able to find a work register. */
|
||||
pic_tmp = gen_rtx_REG (SImode,
|
||||
thumb_find_work_register (saved_regs));
|
||||
emit_insn (gen_pic_load_addr_thumb1 (pic_tmp, pic_rtx));
|
||||
emit_insn (gen_movsi (pic_offset_table_rtx, pic_tmp));
|
||||
emit_insn (gen_pic_load_addr_arm (pic_reg, pic_rtx));
|
||||
emit_insn (gen_pic_add_dot_plus_eight (pic_reg, pic_reg, labelno));
|
||||
}
|
||||
else if (TARGET_THUMB2)
|
||||
{
|
||||
/* Thumb-2 only allows very limited access to the PC. Calculate the
|
||||
address in a temporary register. */
|
||||
if (arm_pic_register != INVALID_REGNUM)
|
||||
{
|
||||
pic_tmp = gen_rtx_REG (SImode,
|
||||
thumb_find_work_register (saved_regs));
|
||||
}
|
||||
else
|
||||
{
|
||||
gcc_assert (!no_new_pseudos);
|
||||
pic_tmp = gen_reg_rtx (Pmode);
|
||||
}
|
||||
|
||||
emit_insn (gen_pic_load_addr_thumb2 (pic_reg, pic_rtx));
|
||||
emit_insn (gen_pic_load_dot_plus_four (pic_tmp, labelno));
|
||||
emit_insn (gen_addsi3 (pic_reg, pic_reg, pic_tmp));
|
||||
}
|
||||
else /* TARGET_THUMB1 */
|
||||
{
|
||||
if (arm_pic_register != INVALID_REGNUM
|
||||
&& REGNO (pic_reg) > LAST_LO_REGNUM)
|
||||
{
|
||||
/* We will have pushed the pic register, so we should always be
|
||||
able to find a work register. */
|
||||
pic_tmp = gen_rtx_REG (SImode,
|
||||
thumb_find_work_register (saved_regs));
|
||||
emit_insn (gen_pic_load_addr_thumb1 (pic_tmp, pic_rtx));
|
||||
emit_insn (gen_movsi (pic_offset_table_rtx, pic_tmp));
|
||||
}
|
||||
else
|
||||
emit_insn (gen_pic_load_addr_thumb1 (pic_reg, pic_rtx));
|
||||
emit_insn (gen_pic_add_dot_plus_four (pic_reg, pic_reg, labelno));
|
||||
}
|
||||
else
|
||||
emit_insn (gen_pic_load_addr_thumb1 (cfun->machine->pic_reg, pic_rtx));
|
||||
emit_insn (gen_pic_add_dot_plus_four (cfun->machine->pic_reg,
|
||||
cfun->machine->pic_reg, labelno));
|
||||
}
|
||||
|
||||
/* Need to emit this whether or not we obey regdecls,
|
||||
since setjmp/longjmp can cause life info to screw up. */
|
||||
emit_insn (gen_rtx_USE (VOIDmode, cfun->machine->pic_reg));
|
||||
emit_insn (gen_rtx_USE (VOIDmode, pic_reg));
|
||||
#endif /* AOF_ASSEMBLER */
|
||||
}
|
||||
|
||||
|
@ -8862,6 +8913,30 @@ vfp_emit_fstmd (int base_reg, int count)
|
|||
return count * 8;
|
||||
}
|
||||
|
||||
/* Emit a call instruction with pattern PAT. ADDR is the address of
|
||||
the call target. */
|
||||
|
||||
void
|
||||
arm_emit_call_insn (rtx pat, rtx addr)
|
||||
{
|
||||
rtx insn;
|
||||
|
||||
insn = emit_call_insn (pat);
|
||||
|
||||
/* The PIC register is live on entry to VxWorks PIC PLT entries.
|
||||
If the call might use such an entry, add a use of the PIC register
|
||||
to the instruction's CALL_INSN_FUNCTION_USAGE. */
|
||||
if (TARGET_VXWORKS_RTP
|
||||
&& flag_pic
|
||||
&& GET_CODE (addr) == SYMBOL_REF
|
||||
&& (SYMBOL_REF_DECL (addr)
|
||||
? !targetm.binds_local_p (SYMBOL_REF_DECL (addr))
|
||||
: !SYMBOL_REF_LOCAL_P (addr)))
|
||||
{
|
||||
require_pic_register ();
|
||||
use_reg (&CALL_INSN_FUNCTION_USAGE (insn), cfun->machine->pic_reg);
|
||||
}
|
||||
}
|
||||
|
||||
/* Output a 'call' insn. */
|
||||
const char *
|
||||
|
@ -11947,14 +12022,13 @@ arm_assemble_integer (rtx x, unsigned int size, int aligned_p)
|
|||
if (NEED_GOT_RELOC && flag_pic && making_const_table &&
|
||||
(GET_CODE (x) == SYMBOL_REF || GET_CODE (x) == LABEL_REF))
|
||||
{
|
||||
if (GET_CODE (x) == SYMBOL_REF
|
||||
&& (CONSTANT_POOL_ADDRESS_P (x)
|
||||
|| SYMBOL_REF_LOCAL_P (x)))
|
||||
fputs ("(GOTOFF)", asm_out_file);
|
||||
else if (GET_CODE (x) == LABEL_REF)
|
||||
fputs ("(GOTOFF)", asm_out_file);
|
||||
else
|
||||
/* See legitimize_pic_address for an explanation of the
|
||||
TARGET_VXWORKS_RTP check. */
|
||||
if (TARGET_VXWORKS_RTP
|
||||
|| (GET_CODE (x) == SYMBOL_REF && !SYMBOL_REF_LOCAL_P (x)))
|
||||
fputs ("(GOT)", asm_out_file);
|
||||
else
|
||||
fputs ("(GOTOFF)", asm_out_file);
|
||||
}
|
||||
fputc ('\n', asm_out_file);
|
||||
return true;
|
||||
|
|
|
@ -26,6 +26,8 @@
|
|||
#ifndef GCC_ARM_H
|
||||
#define GCC_ARM_H
|
||||
|
||||
#include "config/vxworks-dummy.h"
|
||||
|
||||
/* The architecture define. */
|
||||
extern char arm_arch_name[];
|
||||
|
||||
|
|
|
@ -95,6 +95,8 @@
|
|||
; instruction stream.
|
||||
(UNSPEC_STACK_ALIGN 20) ; Doubleword aligned stack pointer. Used to
|
||||
; generate correct unwind information.
|
||||
(UNSPEC_PIC_OFFSET 22) ; A symbolic 12-bit OFFSET that has been treated
|
||||
; correctly for PIC usage.
|
||||
]
|
||||
)
|
||||
|
||||
|
@ -4919,6 +4921,16 @@
|
|||
""
|
||||
)
|
||||
|
||||
(define_insn "pic_offset_arm"
|
||||
[(set (match_operand:SI 0 "register_operand" "=r")
|
||||
(mem:SI (plus:SI (match_operand:SI 1 "register_operand" "r")
|
||||
(unspec:SI [(match_operand:SI 2 "" "X")]
|
||||
UNSPEC_PIC_OFFSET))))]
|
||||
"TARGET_VXWORKS_RTP && TARGET_ARM && flag_pic"
|
||||
"ldr%?\\t%0, [%1,%2]"
|
||||
[(set_attr "type" "load1")]
|
||||
)
|
||||
|
||||
(define_expand "builtin_setjmp_receiver"
|
||||
[(label_ref (match_operand 0 "" ""))]
|
||||
"flag_pic"
|
||||
|
@ -8145,7 +8157,7 @@
|
|||
"TARGET_EITHER"
|
||||
"
|
||||
{
|
||||
rtx callee;
|
||||
rtx callee, pat;
|
||||
|
||||
/* In an untyped call, we can get NULL for operand 2. */
|
||||
if (operands[2] == NULL_RTX)
|
||||
|
@ -8159,9 +8171,19 @@
|
|||
? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
|
||||
: !REG_P (callee))
|
||||
XEXP (operands[0], 0) = force_reg (Pmode, callee);
|
||||
|
||||
pat = gen_call_internal (operands[0], operands[1], operands[2]);
|
||||
arm_emit_call_insn (pat, XEXP (operands[0], 0));
|
||||
DONE;
|
||||
}"
|
||||
)
|
||||
|
||||
(define_expand "call_internal"
|
||||
[(parallel [(call (match_operand 0 "memory_operand" "")
|
||||
(match_operand 1 "general_operand" ""))
|
||||
(use (match_operand 2 "" ""))
|
||||
(clobber (reg:SI LR_REGNUM))])])
|
||||
|
||||
(define_insn "*call_reg_armv5"
|
||||
[(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
|
||||
(match_operand 1 "" ""))
|
||||
|
@ -8239,7 +8261,7 @@
|
|||
"TARGET_EITHER"
|
||||
"
|
||||
{
|
||||
rtx callee;
|
||||
rtx pat, callee;
|
||||
|
||||
/* In an untyped call, we can get NULL for operand 2. */
|
||||
if (operands[3] == 0)
|
||||
|
@ -8253,9 +8275,21 @@
|
|||
? arm_is_long_call_p (SYMBOL_REF_DECL (callee))
|
||||
: !REG_P (callee))
|
||||
XEXP (operands[1], 0) = force_reg (Pmode, callee);
|
||||
|
||||
pat = gen_call_value_internal (operands[0], operands[1],
|
||||
operands[2], operands[3]);
|
||||
arm_emit_call_insn (pat, XEXP (operands[1], 0));
|
||||
DONE;
|
||||
}"
|
||||
)
|
||||
|
||||
(define_expand "call_value_internal"
|
||||
[(parallel [(set (match_operand 0 "" "")
|
||||
(call (match_operand 1 "memory_operand" "")
|
||||
(match_operand 2 "general_operand" "")))
|
||||
(use (match_operand 3 "" ""))
|
||||
(clobber (reg:SI LR_REGNUM))])])
|
||||
|
||||
(define_insn "*call_value_reg_armv5"
|
||||
[(set (match_operand 0 "" "")
|
||||
(call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
|
||||
|
|
|
@ -54,6 +54,8 @@ Boston, MA 02110-1301, USA. */
|
|||
#ifdef __ELF__
|
||||
#ifdef __thumb__
|
||||
#define __PLT__ /* Not supported in Thumb assembler (for now). */
|
||||
#elif defined __vxworks && !defined __PIC__
|
||||
#define __PLT__ /* Not supported by the kernel loader. */
|
||||
#else
|
||||
#define __PLT__ (PLT)
|
||||
#endif
|
||||
|
|
|
@ -1,10 +1,27 @@
|
|||
# Multilibs for VxWorks.
|
||||
LIB1ASMSRC = arm/lib1funcs.asm
|
||||
LIB1ASMFUNCS = _udivsi3 _divsi3 _umodsi3 _modsi3 _dvmd_tls _bb_init_func _call_via_rX _interwork_call_via_rX
|
||||
|
||||
# We want fine grained libraries, so use the new code to build the
|
||||
# floating point emulation libraries.
|
||||
FPBIT = fp-bit.c
|
||||
DPBIT = dp-bit.c
|
||||
|
||||
fp-bit.c: $(srcdir)/config/fp-bit.c
|
||||
echo '#define FLOAT' > fp-bit.c
|
||||
echo '#ifndef __ARMEB__' >> fp-bit.c
|
||||
echo '#define FLOAT_BIT_ORDER_MISMATCH' >> fp-bit.c
|
||||
echo '#endif' >> fp-bit.c
|
||||
cat $(srcdir)/config/fp-bit.c >> fp-bit.c
|
||||
|
||||
dp-bit.c: $(srcdir)/config/fp-bit.c
|
||||
echo '#ifndef __ARMEB__' > dp-bit.c
|
||||
echo '#define FLOAT_BIT_ORDER_MISMATCH' >> dp-bit.c
|
||||
echo '#endif' >> dp-bit.c
|
||||
cat $(srcdir)/config/fp-bit.c >> dp-bit.c
|
||||
|
||||
MULTILIB_OPTIONS = \
|
||||
t4/t4be/t4t/t4tbe/t5/t5be/t5t/t5tbe/txscale/txscalebe
|
||||
|
||||
MULTILIB_DIRNAMES = \
|
||||
ARMARCH4gnu ARMARCH4gnube ARMARCH4_Tgnu ARMARCH4_Tgnube \
|
||||
ARMARCH5gnu ARMARCH5gnube ARMARCH5_Tgnu ARMARCH5_Tgnube \
|
||||
XSCALEgnu XSCALEgnube
|
||||
|
||||
mrtp fPIC \
|
||||
t4/t4be/t4t/t4tbe/t5/t5be/t5t/t5tbe/tstrongarm/txscale/txscalebe
|
||||
MULTILIB_MATCHES = fPIC=fpic
|
||||
# Don't build -fPIC multilibs for kernel or Thumb code.
|
||||
MULTILIB_EXCEPTIONS = fPIC* mrtp/fPIC/*t[45]t*
|
||||
|
|
|
@ -25,13 +25,12 @@ Boston, MA 02110-1301, USA. */
|
|||
|
||||
#define TARGET_OS_CPP_BUILTINS() \
|
||||
do { \
|
||||
builtin_define ("__vxworks"); \
|
||||
if (TARGET_BIG_END) \
|
||||
builtin_define ("ARMEB"); \
|
||||
else \
|
||||
builtin_define ("ARMEL"); \
|
||||
\
|
||||
if (arm_is_xscale) \
|
||||
if (arm_arch_xscale) \
|
||||
builtin_define ("CPU=XSCALE"); \
|
||||
else if (arm_arch5) \
|
||||
builtin_define ("CPU=ARMARCH5"); \
|
||||
|
@ -42,54 +41,70 @@ Boston, MA 02110-1301, USA. */
|
|||
else \
|
||||
builtin_define ("CPU=ARMARCH4"); \
|
||||
} \
|
||||
VXWORKS_OS_CPP_BUILTINS (); \
|
||||
} while (0)
|
||||
|
||||
#undef OVERRIDE_OPTIONS
|
||||
#define OVERRIDE_OPTIONS \
|
||||
do \
|
||||
{ \
|
||||
VXWORKS_OVERRIDE_OPTIONS; \
|
||||
arm_override_options (); \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
/* Subsume the arm/elf.h definition, and add RTP hooks. */
|
||||
#undef SUBTARGET_CPP_SPEC
|
||||
#define SUBTARGET_CPP_SPEC "-D__ELF__" VXWORKS_ADDITIONAL_CPP_SPEC
|
||||
|
||||
#undef CC1_SPEC
|
||||
#define CC1_SPEC \
|
||||
"%{t4: -mlittle-endian -march=armv4 ; \
|
||||
t4be: -mbig-endian -march=armv4 ; \
|
||||
"%{tstrongarm:-mlittle-endian -mcpu=strongarm ; \
|
||||
t4: -mlittle-endian -march=armv4 ; \
|
||||
t4be: -mbig-endian -march=armv4 ; \
|
||||
t4t: -mthumb -mthumb-interwork -mlittle-endian -march=armv4t ; \
|
||||
t4tbe: -mthumb -mthumb-interwork -mbig-endian -march=armv4t ; \
|
||||
t5: -mlittle-endian -march=armv5 ; \
|
||||
t5be: -mbig-endian -march=armv5 ; \
|
||||
t5: -mlittle-endian -march=armv5 ; \
|
||||
t5be: -mbig-endian -march=armv5 ; \
|
||||
t5t: -mthumb -mthumb-interwork -mlittle-endian -march=armv5 ; \
|
||||
t5tbe: -mthumb -mthumb-interwork -mbig-endian -march=armv5 ; \
|
||||
txscale: -mlittle-endian -mcpu=xscale ; \
|
||||
txscalebe: -mbig-endian -mcpu=xscale ; \
|
||||
txscale: -mlittle-endian -mcpu=xscale ; \
|
||||
txscalebe: -mbig-endian -mcpu=xscale ; \
|
||||
: -march=armv4}"
|
||||
|
||||
/* Pass -EB for big-endian targets. */
|
||||
#define VXWORKS_ENDIAN_SPEC \
|
||||
"%{mbig-endian|t4be|t4tbe|t5be|t5tbe|txscalebe:-EB}"
|
||||
|
||||
/* The -Q options from svr4.h aren't understood and must be removed. */
|
||||
#undef ASM_SPEC
|
||||
#define ASM_SPEC \
|
||||
"%{v:-V} %{n} %{T} %{Ym,*} %{Yd,*} %{Wa,*:%*}"
|
||||
"%{v:-V} %{n} %{T} %{Ym,*} %{Yd,*} %{Wa,*:%*} " VXWORKS_ENDIAN_SPEC
|
||||
|
||||
/* VxWorks does all the library stuff itself. */
|
||||
#undef LIB_SPEC
|
||||
#define LIB_SPEC ""
|
||||
#undef LINK_SPEC
|
||||
#define LINK_SPEC VXWORKS_LINK_SPEC " " VXWORKS_ENDIAN_SPEC
|
||||
|
||||
/* VxWorks uses object files, not loadable images. make linker just
|
||||
combine objects. */
|
||||
#undef LINK_SPEC
|
||||
#define LINK_SPEC "-r"
|
||||
#undef LIB_SPEC
|
||||
#define LIB_SPEC VXWORKS_LIB_SPEC
|
||||
|
||||
/* VxWorks provides the functionality of crt0.o and friends itself. */
|
||||
#undef STARTFILE_SPEC
|
||||
#define STARTFILE_SPEC ""
|
||||
#undef STARTFILE_SPEC
|
||||
#define STARTFILE_SPEC VXWORKS_STARTFILE_SPEC
|
||||
|
||||
#undef ENDFILE_SPEC
|
||||
#define ENDFILE_SPEC ""
|
||||
#undef ENDFILE_SPEC
|
||||
#define ENDFILE_SPEC VXWORKS_ENDFILE_SPEC
|
||||
|
||||
#undef TARGET_VERSION
|
||||
#define TARGET_VERSION fputs (" (ARM/VxWorks)", stderr);
|
||||
#undef TARGET_VERSION
|
||||
#define TARGET_VERSION fputs (" (ARM/VxWorks)", stderr);
|
||||
|
||||
/* There is no default multilib. */
|
||||
#undef MULTILIB_DEFAULTS
|
||||
|
||||
#undef ASM_FILE_START
|
||||
#define ASM_FILE_START(STREAM) \
|
||||
do \
|
||||
{ \
|
||||
fprintf (STREAM, "%s Generated by GCC %s for ARM/VxWorks\n", \
|
||||
ASM_COMMENT_START, version_string); \
|
||||
} \
|
||||
while (0)
|
||||
#define FPUTYPE_DEFAULT FPUTYPE_VFP
|
||||
|
||||
#undef FUNCTION_PROFILER
|
||||
#define FUNCTION_PROFILER VXWORKS_FUNCTION_PROFILER
|
||||
|
||||
/* We want to be compatible with a version of "2.96" at one point in
|
||||
the past before this macro was changed. */
|
||||
#undef DEFAULT_STRUCTURE_SIZE_BOUNDARY
|
||||
#define DEFAULT_STRUCTURE_SIZE_BOUNDARY 8
|
||||
|
|
|
@ -63,6 +63,7 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
|
|||
#define WINT_TYPE_SIZE 16
|
||||
|
||||
/* Dwarf2 unwind info is not supported. */
|
||||
#undef DWARF2_UNWIND_INFO
|
||||
#define DWARF2_UNWIND_INFO 0
|
||||
|
||||
/* VxWorks uses DWARF2. */
|
||||
|
|
|
@ -92,7 +92,9 @@ extern void vxworks_override_options (void);
|
|||
|
||||
/* VxWorks requires special handling of constructors and destructors.
|
||||
All VxWorks configurations must use these functions. */
|
||||
#undef TARGET_ASM_CONSTRUCTOR
|
||||
#define TARGET_ASM_CONSTRUCTOR vxworks_asm_out_constructor
|
||||
#undef TARGET_ASM_DESTRUCTOR
|
||||
#define TARGET_ASM_DESTRUCTOR vxworks_asm_out_destructor
|
||||
extern void vxworks_asm_out_constructor (rtx symbol, int priority);
|
||||
extern void vxworks_asm_out_destructor (rtx symbol, int priority);
|
||||
|
|
Loading…
Add table
Reference in a new issue