aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Mitchell <mark@codesourcery.com>2005-04-01 20:32:32 +0000
committerMark Mitchell <mark@codesourcery.com>2005-04-01 20:32:32 +0000
commit2e297bfc5dde9de799e7343d4849e44046963fa3 (patch)
treed42647b53941364a8ca57ce0c6a68c17a2b9cc94
parentedcc5ccc985fcd569d3899184325cab5439f251f (diff)
Merge to merge-csl-arm-csl_3_4_3-linux-1.
git-svn-id: https://gcc.gnu.org/svn/gcc/branches/csl-3_4_3-linux-branch@97418 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--ChangeLog.csl4
-rw-r--r--gcc/ChangeLog.csl33
-rw-r--r--gcc/ChangeLog.csl-arm282
-rw-r--r--gcc/Makefile.in2
-rw-r--r--gcc/calls.c63
-rw-r--r--gcc/config.gcc6
-rw-r--r--gcc/config/arm/arm-protos.h15
-rw-r--r--gcc/config/arm/arm.c636
-rw-r--r--gcc/config/arm/arm.h108
-rw-r--r--gcc/config/arm/arm.md130
-rw-r--r--gcc/config/arm/iwmmxt.md4
-rw-r--r--gcc/config/arm/lib1funcs.asm6
-rw-r--r--gcc/config/arm/libunwind.S5
-rw-r--r--gcc/config/arm/linux-eabi.h11
-rw-r--r--gcc/config/arm/linux-elf.h6
-rw-r--r--gcc/config/arm/netbsd-elf.h5
-rw-r--r--gcc/config/arm/pr-support.c372
-rw-r--r--gcc/config/arm/symbian.h9
-rw-r--r--gcc/config/arm/t-bpabi8
-rw-r--r--gcc/config/arm/t-symbian2
-rw-r--r--gcc/config/arm/t-wrs-linux2
-rw-r--r--gcc/config/arm/unwind-arm.c297
-rw-r--r--gcc/config/arm/wrs-linux.h14
-rw-r--r--gcc/config/elfos.h10
-rw-r--r--gcc/config/ia64/ia64.h2
-rwxr-xr-xgcc/configure23
-rw-r--r--gcc/configure.ac25
-rw-r--r--gcc/doc/invoke.texi2
-rw-r--r--gcc/doc/tm.texi5
-rw-r--r--gcc/dwarf2out.c10
-rw-r--r--gcc/expr.h2
-rw-r--r--gcc/function.c55
-rw-r--r--gcc/haifa-sched.c6
-rw-r--r--gcc/jump.c8
-rw-r--r--gcc/optabs.c37
-rw-r--r--gcc/optabs.h3
-rw-r--r--gcc/opts.c8
-rw-r--r--gcc/postreload.c4
-rw-r--r--gcc/stmt.c32
-rw-r--r--gcc/target-def.h4
-rw-r--r--gcc/target.h3
-rw-r--r--gcc/testsuite/gcc.dg/divmod-1.c9
-rw-r--r--gcc/testsuite/gcc.dg/pack-test-4.c1
-rw-r--r--gcc/testsuite/gcc.misc-tests/bprob.exp2
-rw-r--r--gcc/testsuite/lib/g++.exp33
-rw-r--r--gcc/testsuite/lib/profopt.exp11
-rw-r--r--gcc/unwind-arm.h5
-rw-r--r--libstdc++-v3/testsuite/lib/libstdc++.exp20
48 files changed, 1856 insertions, 484 deletions
diff --git a/ChangeLog.csl b/ChangeLog.csl
index 271d644e789..e223bcc0ac6 100644
--- a/ChangeLog.csl
+++ b/ChangeLog.csl
@@ -1,3 +1,7 @@
+2005-03-30 Mark Mitchell <mark@codesourcery.com>
+
+ Merge to merge-csl-arm-csl_3_4_3-linux-1.
+
2005-03-23 Mark Mitchell <mark@codesourcery.com>
Backport from mainline:
diff --git a/gcc/ChangeLog.csl b/gcc/ChangeLog.csl
index e9e9283a291..82830f7a0ae 100644
--- a/gcc/ChangeLog.csl
+++ b/gcc/ChangeLog.csl
@@ -1,3 +1,36 @@
+2005-03-25 Mark Mitchell <mark@codesourcery.com>
+
+ Backport from 3.4 branch:
+ * gcc.dg/altivec-1.c: Pass -mcpu=7400 along with -maltivec.
+ * gcc.dg/altivec-2.c: Likewise.
+ * gcc.dg/altivec-3.c: Likewise.
+ * gcc.dg/altivec-4.c: Likewise.
+ * gcc.dg/altivec-5.c: Likewise.
+ * gcc.dg/altivec-6.c: Likewise.
+ * gcc.dg/altivec-7.c: Likewise.
+ * gcc.dg/altivec-8.c: Likewise.
+ * gcc.dg/altivec-9.c: Likewise.
+ * gcc.dg/altivec-10.c: Likewise.
+ * gcc.dg/altivec-11.c: Likewise.
+ * gcc.dg/altivec-12.c: Likewise.
+ * gcc.dg/altivec-13.c: Likewise.
+ * gcc.dg/altivec-14.c: Likewise.
+ * gcc.dg/altivec-15.c: Likewise.
+ * gcc.dg/altivec-16.c: Likewise.
+ * gcc.dg/altivec-17.c: Likewise.
+ * g++.dg/ext/altivec-1.C: Likewise.
+ * g++.dg/ext/altivec-2.C: Likewise.
+ * g++.dg/ext/altivec-3.C: Likewise.
+ * g++.dg/ext/altivec-4.C: Likewise.
+ * g++.dg/ext/altivec-5.C: Likewise.
+ * g++.dg/ext/altivec-6.C: Likewise.
+ * g++.dg/ext/altivec-7.C: Likewise.
+ * g++.dg/ext/altivec-8.C: Likewise.
+ * g++.dg/ext/altivec-9.C: Likewise.
+ * g++.dg/ext/altivec-10.C: Likewise.
+ * g++.dg/ext/altivec-11.C: Likewise.
+ * g++.dg/ext/altivec-12.C: Likewise.
+
2005-01-31 Mark Mitchell <mark@codesourcery.com>
* gcc.c (main): Use set_spec.
diff --git a/gcc/ChangeLog.csl-arm b/gcc/ChangeLog.csl-arm
index 5b336c8d635..58683684515 100644
--- a/gcc/ChangeLog.csl-arm
+++ b/gcc/ChangeLog.csl-arm
@@ -1,3 +1,285 @@
+2005-03-30 Paul Brook <pau@codesourcery.com>
+
+ * dwarf2out.c (multiple_reg_loc_descriptor): Handle single REG.
+ * config/arm/arm.c (arm_dwarf_register_span): New function.
+ (TARGET_DWARF_REGISTER_SPAN): Define.
+ * doc/tm.dexi: Update documentation for TARGET_DWARF_REGISTER_SPAN.
+
+2005-03-30 Paul Brook <paul@codesourcery.com>
+
+ * optabs.c (expand_twoval_binop_libfunc): Call protect_from_queue.
+ * testsuite/gcc.dg/divmod-1.c: New test.
+
+2005-03-29 Paul Brook <paul@codesourcery.com>
+
+ * config/arm/arm-protos.h (arm_dbx_register_number): Add prototype.
+ * config/arm/arm.c (arm_dbx_register_number): New function.
+ * config/arm/arm.h (IS_FPA_REGNUM, DBX_REGISTER_NUMBER): Define.
+
+2005-03-28 Julian Brown <julian@codesourcery.com>
+
+ * config/arm/arm.c (arm_handle_notshared_attribute): Protect
+ prototype and implementation with preprocessor conditional.
+ (arm_pad_reg_upwards): Add ATTRIBUTE_UNUSED.
+
+2005-03-28 Daniel Jacobowitz <dan@codesourcery.com>
+ Phil Blundell <philb@gnu.org>
+
+ * configure.ac: Add test for ARM TLS support.
+ * configure: Regenerated.
+ * haifa-sched.c (schedule_block): Only count INSNs.
+ * jump.c (duplicate_loop_exit_test): Check targetm.cannot_copy_insn_p.
+ * postreload.c (reload_cse_simplify_operands): Handle deleted labels.
+ * config/arm/arm-protos.h (legitimize_tls_address)
+ (thumb_legitimize_address, tls_symbolic_operand, arm_tls_operand_p)
+ (tls_mentioned_p, arm_output_addr_const_extra): New prototypes.
+ (thumb_legitimize_pic_address): Delete.
+ * config/arm/arm.c: Include "gt-arm.h".
+ (arm_cannot_copy_insn_p, load_tls_operand)
+ (pcrel_constant_p, get_tls_get_addr, arm_load_tp)
+ (legitimize_tls_address, thumb_legitimize_address)
+ (arm_tls_operand_p, tls_symbolic_operand, move_input_operand)
+ (tls_mentioned_p, arm_init_tls_builtins)
+ (arm_emit_tls_decoration, arm_output_addr_const_extra): New functions.
+ (TARGET_CANNOT_COPY_INSN_P, TARGET_CANNOT_FORCE_CONST_MEM): Define.
+ (target_thread_switch, target_thread_pointer): New.
+ (arm_pic_register): Change to unsigned.
+ (arm_override_options): Handle -mtp=.
+ (legitimize_pic_address): Ignore UNSPECs.
+ (arm_legitimate_address_p): Handle TLS and pcrel symbols.
+ (thumb_legitimate_address_p): Handle TLS and pcrel symbols.
+ (arm_legitimize_address): Handle TLS.
+ (arm_regno_class): Handle RETURN_REG.
+ (arm_init_builtins): Call arm_init_tls_builtins.
+ (arm_expand_builtin): Handle ARM_BUILTIN_THREAD_POINTER.
+ (arm_encode_section_info): Call default_encode_section_info.
+ * config/arm/arm.h (target_thread_switch): Add declaration.
+ (TARGET_HARD_TP, TARGET_SOFT_TP, TARGET_LINUX_TP): Define.
+ (TARGET_OPTIONS): Add -mtp=.
+ (enum arm_tp_type): New.
+ (target_thread_pointer): Add declaration.
+ (enum reg_class, REG_CLASS_NAMES, REG_CLASS_CONTENTS)
+ (REG_CLASS_FROM_LETTER): Add RETURN_REG.
+ (LEGITIMATE_CONSTANT_P): Handle TLS.
+ (THUMB_LEGITIMIZE_ADDRESS): Call thumb_legitimize_address.
+ (arm_pic_register): Change type to unsigned.
+ (LEGITIMATE_PIC_OPERAND_P): Handle TLS.
+ (OUTPUT_ADDR_CONST_EXTRA): Call arm_output_addr_const_extra.
+ (PREDICATE_CODES): Add move_input_operand.
+ (enum arm_builtins): Add ARM_BUILTIN_THREAD_POINTER.
+ * config/arm/arm.md: Add UNSPEC_TLS.
+ (movsi): Handle TLS.
+ (arm_movsi_insn, thumb_movsi_insn): Use move_input_operand.
+ (pic_add_dot_plus_four, pic_add_dot_plus_eight): Allow for
+ non-PIC.
+ (tls_load_dot_plus_four, tls_load_dot_plus_eight): New insns
+ and new peepholes to create them.
+ (load_tp_hard, load_tp_soft): New insns.
+
+2005-03-22 Mark Mitchell <mark@codesourcery.com>
+
+ Merge from mainline.
+ 2005-01-14 Richard Earnshaw <rearnsha@arm.com>
+ PR target/7525
+ * arm.h (struct machine_function): Add call_via field.
+ (thumb_call_via_label): Declare.
+ * arm.c (thumb_call_via_label): New variable.
+ (thumb_call_reg_needed): New variable.
+ (arm_output_function_epilogue): For Thumb code, output any per-function
+ call-indirect trampolines.
+ (thumb_call_via_reg): New function.
+ (arm_file_end): New function.
+ (TARGET_ASM_FILE_END): Call arm_file_end.
+ (aof_file_end): Likewise.
+ * arm-protos.h (thumb_call_via_reg): Declare.
+ * arm.md (call_reg_thumb, call_value_reg_thumb): Call
+ thumb_call_via_reg in normal case.
+
+2005-03-22 Mark Mitchell <mark@codesourcery.com>
+
+ Merge from csl-3_4_3-linux-branch.
+ 2005-01-31 Mark Mitchell <mark@codesourcery.com>
+ * gcc.c (main): Use set_spec.
+ 2005-01-25 Mark Mitchell <mark@codesourcery.com>
+ * gcc.c (SYSROOT_SPEC): New macro.
+ (sysroot_spec): New variable.
+ (static_specs): Add sysroot_spec.
+ (main): Pass --sysroot to the linker.
+
+2005-03-15 Daniel Jacobowitz <dan@codesourcery.com>
+
+ * config/arm/arm.h (CONDITIONAL_REGISTER_USAGE): Don't clear
+ call_used_regs for wCG registers.
+
+2005-03-14 Julian Brown <julian@codesourcery.com>
+
+ * config/arm/lib1funcs.asm (ashldi3): Don't define on SymbianOS.
+ (aeabi_llsl): Likewise.
+ (ashrdi3): Likewise.
+ (aeabi_lasr): Likewise.
+ (lshrdi3): Likewise.
+ (aeabi_llsr): Likewise.
+
+2005-03-10 Julian Brown <julian@codesourcery.com>
+
+ * config.gcc: Disable shared libgcc for SymbianOS.
+ * config/arm/t-symbian (LIB2ADDEH): Include config/arm/pr-support.c.
+
+2005-03-07 Daniel Jacobowitz <dan@codesourcery.com>
+
+ * config/arm/arm.c (arm_all_abis): Add aapcs-linux.
+ (arm_override_options): Use TARGET_AAPCS_BASED.
+ * config/arm/arm.h (enum arm_abi_type): Add ARM_ABI_AAPCS_LINUX.
+ (PTRDIFF_TYPE): Use int for AAPCS.
+ (DEFAULT_SHORT_ENUMS): Use false for aapcs-linux.
+ * config/arm/linux-eabi.h (ARM_DEFAULT_ABI, WCHAR_TYPE): Define.
+ (DEFAULT_SHORT_ENUMS): Delete.
+ * doc/invoke.texi (ARM Options): Document -mabi=aapcs-linux.
+
+2005-03-02 Daniel Jacobowitz <dan@codesourcery.com>
+
+ * config/arm/linux-elf.h (ARM_FUNCTION_PROFILER): Do not use (PLT)
+ for Thumb.
+ * config/arm/netbsd-elf.h (ARM_FUNCTION_PROFILER): Likewise.
+
+2005-02-25 Julian Brown <julian@codesourcery.com>
+
+ * config/elfos.h (MAKE_DECL_ONE_ONLY): Redefined to stop DECL_WEAK
+ from being used for symbols with vague linkage when
+ HAVE_GAS_COMDAT_GROUP is true.
+
+2004-02-15 Mark Mitchell <mark@codesourcery.com>
+
+ * configure.ac: Never set STMP_FIXINC or STMP_FIXPROTO when
+ building a Canadian cross.
+ * configure: Regenerated.
+
+ * unwind-arm.h (abort): Use a prototype, not a K&R declaration.
+ (__gnu_unwind_execute): Declare.
+ * config/arm/lib1funcs.asm: Do not include libunwind.S.
+ * config/arm/libunwind.S: Include lib1funcs.asm.
+ * config/arm/t-bpabi (LIB1ASMFUNCS): Remove _unwind.
+ (LIB2ADDEH): Add $(srcdir)/config/arm/libunwind.S.
+
+2005-02-16 Paul Brook <paul@codesourcery.com>
+
+ * config/arm/unwind-arm.c (__gnu_Unwind_Find_exidx): Add prototype.
+ (search_EIT_table): New function.
+ (get_eit_entry): Use them.
+ (EIT_comparator): Remove.
+
+2005-02-14 Julian Brown <julian@codesourcery.com>
+
+ * config/arm/t-bpabi (LIB2ADDEH): Add pr-support.c
+ * unwind-arm.c (next_unwind_byte): Moved to file pr-support.c.
+ (__gnu_unwind_execute): Likewise.
+ (__gnu_unwind_frame): Likewise.
+ (_Unwind_GetLanguageSpecificData): Likewise.
+ (_Unwind_GetRegionStart): Likewise.
+ * pr-support.c: New file.
+ (selfrel_offset31, EHT16, EHT32): Duplicated from unwind-arm.c.
+
+2005-01-28 Paul Brook <paul@codesourcery.com>
+
+ * Makefile.in (opts.o): Depend on $(TARGET_H).
+ * opts.c: Include target.h.
+ (decode_options): Use targetm.unwind_tables_default.
+ * target-def.h (TARGET_UNWIND_TABLES_DEFAULT): Define.
+ (TARGET_INITIALIZER): Use it
+ * target.h (struct gcc_target): Add unwind_tables_default.
+ * config/ia64/ia64.h (TARGET_UNWIND_TABLES_DEFAULT): Define.
+
+2005-01-27 Paul Brook <paul@codesourcery.com>
+
+ * config/arm/arm.c (arm_init_libfuncs): Clear mod optabs.
+
+2005-01-27 Paul Brook <paul@codesourcery.com>
+
+ * config/arm/arm.h (ARM_EABI_UNWIND_TABLES): Fix logic.
+
+2005-01-27 Paul Brook <paul@codesourcery.com>
+
+ * config/arm/arm.c (arm_compute_func_type): Fix noreturn logic.
+
+2004-01-26 Mark Mitchell <mark@codesourcery.com>
+
+ * config/arm/arm.h (ARM_EABI_CTORS_SECTION_OP): Do not define
+ if a definition has already been provided.
+ (ARM_EABI_DTORS_SECTION_OP): Likewise.
+ * config/arm/symbian.h (ARM_EABI_CTORS_SECTION_OP): Define.
+ (ARM_EABI_DTORS_SECTION_OP): Likewise.
+
+2005-01-26 Julian Brown <julian@codesourcery.com>
+
+ Backport:
+ 2004-11-24 Richard Sandiford <rsandifo@redhat.com>
+
+ * optabs.h (force_expand_binop): Declare.
+ * optabs.c (force_expand_binop): Export.
+ * stmt.c (shift_return_value): Delete.
+ (expand_return): Don't call it.
+ * expr.h (shift_return_value): Declare.
+ * calls.c (shift_returned_value): Delete in favor of...
+ (shift_return_value): ...this new function. Leave the caller to check
+ for non-BLKmode values passed in the msb of a register. Take said
+ mode and a shift direction as argument. Operate on the hard function
+ value, not a pseudo.
+ (expand_call): Adjust accordingly.
+ * function.c (expand_function_start): If a non-BLKmode return value
+ is padded at the last significant end of the return register, use the
+ return value's natural mode for the DECL_RESULT, not the mode of the
+ padded register.
+ (expand_function_end): Shift the same sort of return values left by
+ the appropriate amount.
+
+ Backport:
+ 2004-09-04 Richard Sandiford <rsandifo@redhat.com>
+
+ * optabs.c (simplify_expand_binop, force_expand_binop): New functions.
+ (only these parts of the patch are applied)
+
+ * config/arm/arm-protos.h (arm_must_pass_in_stack): Declare.
+ (arm_pad_arg_upward): Declare:
+ (arm_pad_reg_upward): Declare.
+ * config/arm/arm.c (TARGET_RETURN_IN_MSB): Define target hook as...
+ (arm_return_in_msb): New function, specifying when values returned in
+ registers should be aligned to the most-significant end.
+ (arm_function_value): If necessary (aggregates and complex values of
+ word size or less), promote the return type of a function to SImode to
+ enable padding to word size.
+ (arm_must_pass_in_stack): New function, returns false for small
+ aggregates so they can be passed in registers (the default
+ implementation passes them in the stack).
+ (arm_pad_arg_upward): New function, fixes argument padding on the
+ stack in big-endian AAPCS mode.
+ (arm_pad_reg_upward): New function, fixes argument padding in
+ registers in big-endian AAPCS mode.
+ * config/arm/arm.h (PROMOTE_FUNCTION_MODE): modes of mode class
+ MODE_COMPLEX_INT are also promoted to SImode.
+ (MUST_PASS_IN_STACK): Define.
+ (FUNCTION_ARG_PADDING): Define.
+ (BLOCK_REG_PADDING): Define.
+ (PAD_VARARGS_DOWN): For AAPCS, varargs are always padded upwards
+ regardless of endianness.
+
+2005-01-25 Paul Brook <paul@codesourcery.com>
+
+ * config/arm/arm.c (arm_compute_func_type): Don't use
+ current_function_nothrow.
+
+2005-01-22 Paul Brook <paul@codesourcery.com>
+
+ * config/arm/arm.md: Use "Uy" constraint for wcgr load/stores.
+
+2005-01-21 Paul Brook <paul@codesourcery.com>
+
+ * config/arm/arm.h (ARM_DTORS_SECTION_ASM_OP): Define.
+ (DTORS_SECTION_ASM_OP): Conditionalize on TARGET_AAPCS_BASED.
+
+2005-01-20 Paul Brook <paul@codesourcery.com>
+
+ * config/arm/arm.md (insv): Use gen_int_mode.
+
2004-01-05 Julian Brown <julian@codesourcery.com>
* config/arm/arm.c (arm_return_in_memory): Treat complex types
diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index 52b310c062a..0b066cf5bc1 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -1536,7 +1536,7 @@ diagnostic.o : diagnostic.c $(DIAGNOSTIC_H) real.h \
input.h toplev.h intl.h langhooks.h $(LANGHOOKS_DEF_H)
opts.o : opts.c opts.h options.h toplev.h $(CONFIG_H) $(SYSTEM_H) \
coretypes.h $(TREE_H) $(TM_H) langhooks.h $(GGC_H) $(RTL_H) \
- output.h $(DIAGNOSTIC_H) $(TM_P_H) $(INSN_ATTR_H) intl.h
+ output.h $(DIAGNOSTIC_H) $(TM_P_H) $(INSN_ATTR_H) intl.h $(TARGET_H)
targhooks.o : targhooks.c targhooks.h $(CONFIG_H) $(SYSTEM_H) \
coretypes.h $(TREE_H) $(TM_H) $(RTL_H) $(TM_P_H) function.h \
output.h toplev.h
diff --git a/gcc/calls.c b/gcc/calls.c
index c76c0316df7..9cd9dba4a70 100644
--- a/gcc/calls.c
+++ b/gcc/calls.c
@@ -149,7 +149,6 @@ static int check_sibcall_argument_overlap (rtx, struct arg_data *, int);
static int combine_pending_stack_adjustment_and_call (int, struct args_size *,
int);
static tree fix_unsafe_tree (tree);
-static bool shift_returned_value (tree, rtx *);
#ifdef REG_PARM_STACK_SPACE
static rtx save_fixed_argument_area (int, rtx, int *, int *);
@@ -2025,31 +2024,28 @@ fix_unsafe_tree (tree t)
}
-/* If function value *VALUE was returned at the most significant end of a
- register, shift it towards the least significant end and convert it to
- TYPE's mode. Return true and update *VALUE if some action was needed.
+/* Given that a function returns a value of mode MODE at the most
+ significant end of hard register VALUE, shift VALUE left or right
+ as specified by LEFT_P. Return true if some action was needed. */
- TYPE is the type of the function's return value, which is known not
- to have mode BLKmode. */
-
-static bool
-shift_returned_value (tree type, rtx *value)
+bool
+shift_return_value (enum machine_mode mode, bool left_p, rtx value)
{
- if (targetm.calls.return_in_msb (type))
- {
- HOST_WIDE_INT shift;
+ HOST_WIDE_INT shift;
- shift = (GET_MODE_BITSIZE (GET_MODE (*value))
- - BITS_PER_UNIT * int_size_in_bytes (type));
- if (shift > 0)
- {
- *value = expand_binop (GET_MODE (*value), lshr_optab, *value,
- GEN_INT (shift), 0, 1, OPTAB_WIDEN);
- *value = convert_to_mode (TYPE_MODE (type), *value, 0);
- return true;
- }
- }
- return false;
+ if (!(REG_P (value) && HARD_REGISTER_P (value)))
+ abort ();
+ shift = GET_MODE_BITSIZE (GET_MODE (value)) - GET_MODE_BITSIZE (mode);
+ if (shift == 0)
+ return false;
+
+ /* Use ashr rather than lshr for right shifts. This is for the benefit
+ of the MIPS port, which requires SImode values to be sign-extended
+ when stored in 64-bit registers. */
+ if (!force_expand_binop (GET_MODE (value), left_p ? ashl_optab : ashr_optab,
+ value, GEN_INT (shift), value, 1, OPTAB_WIDEN))
+ abort ();
+ return true;
}
/* Generate all the code for a function call
@@ -3146,6 +3142,20 @@ expand_call (tree exp, rtx target, int ignore)
next_arg_reg, valreg, old_inhibit_defer_pop, call_fusage,
flags, & args_so_far);
+ /* If a non-BLKmode value is returned at the most significant end
+ of a register, shift the register right by the appropriate amount
+ and update VALREG accordingly. BLKmode values are handled by the
+ group load/store machinery below. */
+ if (!structure_value_addr
+ && !pcc_struct_value
+ && TYPE_MODE (TREE_TYPE (exp)) != BLKmode
+ && targetm.calls.return_in_msb (TREE_TYPE (exp)))
+ {
+ if (shift_return_value (TYPE_MODE (TREE_TYPE (exp)), false, valreg))
+ sibcall_failure = 1;
+ valreg = gen_rtx_REG (TYPE_MODE (TREE_TYPE (exp)), REGNO (valreg));
+ }
+
/* If call is cse'able, make appropriate pair of reg-notes around it.
Test valreg so we don't crash; may safely ignore `const'
if return type is void. Disable for PARALLEL return values, because
@@ -3357,12 +3367,7 @@ expand_call (tree exp, rtx target, int ignore)
sibcall_failure = 1;
}
else
- {
- if (shift_returned_value (TREE_TYPE (exp), &valreg))
- sibcall_failure = 1;
-
- target = copy_to_reg (valreg);
- }
+ target = copy_to_reg (valreg);
if (targetm.calls.promote_function_return(funtype))
{
diff --git a/gcc/config.gcc b/gcc/config.gcc
index ea5ba3f5dec..001f9605224 100644
--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -670,7 +670,7 @@ arm*-*-linux*) # ARM GNU/Linux with ELF
extra_parts="crtbegin.o crtbeginS.o crtend.o crtendS.o"
gnu_ld=yes
case ${target} in
- arm*-*-linux-gnueabi|arm-wrs-linux-gnu)
+ arm*-*-linux-gnueabi)
tm_file="$tm_file arm/bpabi.h arm/linux-eabi.h"
tmake_file="$tmake_file arm/t-arm-elf arm/t-bpabi arm/t-linux-eabi"
# The BPABI long long divmod functions return a 128-bit value in
@@ -680,7 +680,7 @@ arm*-*-linux*) # ARM GNU/Linux with ELF
# The EABI requires the use of __cxa_atexit.
default_use_cxa_atexit=yes
case ${target} in
- arm-wrs-linux-gnu)
+ arm-wrs-linux-gnueabi)
tm_file="$tm_file arm/wrs-linux.h"
tmake_file="$tmake_file arm/t-wrs-linux"
;;
@@ -717,7 +717,7 @@ arm*-*-eabi* | arm*-*-symbianelf* )
tm_file="${tm_file} arm/symbian.h"
# We do not include t-bpabi for Symbian OS because the system
# provides its own implementation of the BPABI functions.
- tmake_file="${tmake_file} t-slibgcc-elf-ver arm/t-symbian"
+ tmake_file="${tmake_file} arm/t-symbian"
;;
esac
tm_file="${tm_file} arm/aout.h arm/arm.h"
diff --git a/gcc/config/arm/arm-protos.h b/gcc/config/arm/arm-protos.h
index 81bb49597ce..c0595983c5a 100644
--- a/gcc/config/arm/arm-protos.h
+++ b/gcc/config/arm/arm-protos.h
@@ -1,5 +1,5 @@
/* Prototypes for exported functions defined in arm.c and pe.c
- Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004
+ Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005
Free Software Foundation, Inc.
Contributed by Richard Earnshaw (rearnsha@arm.com)
Minor hacks by Nick Clifton (nickc@cygnus.com)
@@ -39,6 +39,7 @@ extern HOST_WIDE_INT arm_compute_initial_elimination_offset (unsigned int,
extern HOST_WIDE_INT thumb_compute_initial_elimination_offset (unsigned int,
unsigned int);
extern void arm_output_fn_unwind (FILE *, bool);
+extern unsigned int arm_dbx_register_number (unsigned int);
#ifdef TREE_CODE
extern int arm_return_in_memory (tree);
@@ -52,13 +53,17 @@ extern int arm_split_constant (RTX_CODE, enum machine_mode, rtx,
extern RTX_CODE arm_canonicalize_comparison (RTX_CODE, rtx *);
extern int legitimate_pic_operand_p (rtx);
extern rtx legitimize_pic_address (rtx, enum machine_mode, rtx);
+extern rtx legitimize_tls_address (rtx, unsigned int, rtx);
extern int arm_legitimate_address_p (enum machine_mode, rtx, RTX_CODE, int);
extern int thumb_legitimate_address_p (enum machine_mode, rtx, int);
extern int thumb_legitimate_offset_p (enum machine_mode, HOST_WIDE_INT);
extern rtx arm_legitimize_address (rtx, rtx, enum machine_mode);
+extern rtx thumb_legitimize_address (rtx, rtx, enum machine_mode);
extern int arm_const_double_rtx (rtx);
extern int neg_const_double_rtx_ok_for_fpa (rtx);
extern enum reg_class vfp_secondary_reload_class (enum machine_mode, rtx);
+extern int tls_symbolic_operand (rtx, enum machine_mode);
+extern bool arm_tls_operand_p (rtx x);
/* Predicates. */
extern int s_register_operand (rtx, enum machine_mode);
@@ -108,6 +113,7 @@ extern int arm_no_early_alu_shift_dep (rtx, rtx);
extern int arm_no_early_alu_shift_value_dep (rtx, rtx);
extern int arm_no_early_mul_dep (rtx, rtx);
+extern int tls_mentioned_p (rtx);
extern int symbol_mentioned_p (rtx);
extern int label_mentioned_p (rtx);
extern RTX_CODE minmax_code (rtx);
@@ -153,12 +159,17 @@ extern const char * arm_output_load_gr (rtx *);
extern const char *vfp_output_fstmx (rtx *);
extern void arm_set_return_address (rtx, rtx);
+extern bool arm_output_addr_const_extra (FILE *, rtx);
+
#if defined TREE_CODE
extern rtx arm_function_arg (CUMULATIVE_ARGS *, enum machine_mode, tree, int);
extern void arm_init_cumulative_args (CUMULATIVE_ARGS *, tree, rtx, tree);
extern rtx arm_va_arg (tree, tree);
extern int arm_function_arg_pass_by_reference (CUMULATIVE_ARGS *,
enum machine_mode, tree, int);
+extern bool arm_must_pass_in_stack (enum machine_mode, tree);
+extern bool arm_pad_arg_upward (enum machine_mode, tree);
+extern bool arm_pad_reg_upward (enum machine_mode, tree, int);
extern bool arm_needs_doubleword_align (enum machine_mode, tree);
extern rtx arm_function_value(tree, tree);
#endif
@@ -190,10 +201,10 @@ extern int thumb_shiftable_const (unsigned HOST_WIDE_INT);
extern void thumb_final_prescan_insn (rtx);
extern const char *thumb_load_double_from_address (rtx *);
extern const char *thumb_output_move_mem_multiple (int, rtx *);
+extern const char *thumb_call_via_reg (rtx);
extern void thumb_expand_movstrqi (rtx *);
extern int thumb_cmp_operand (rtx, enum machine_mode);
extern int thumb_cbrch_target_operand (rtx, enum machine_mode);
-extern rtx *thumb_legitimize_pic_address (rtx, enum machine_mode, rtx);
extern int thumb_go_if_legitimate_address (enum machine_mode, rtx);
extern rtx arm_return_addr (int, rtx);
extern void thumb_reload_out_hi (rtx *);
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index c43426e12b7..c75dbe94210 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -1,6 +1,6 @@
/* Output routines for GCC for ARM.
Copyright (C) 1991, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
- 2002, 2003, 2004 Free Software Foundation, Inc.
+ 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
Contributed by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl)
and Martin Simmons (@harleqn.co.uk).
More major hacks by Richard Earnshaw (rearnsha@arm.com).
@@ -113,7 +113,9 @@ static unsigned long arm_isr_value (tree);
static unsigned long arm_compute_func_type (void);
static tree arm_handle_fndecl_attribute (tree *, tree, tree, int, bool *);
static tree arm_handle_isr_attribute (tree *, tree, tree, int, bool *);
+#if TARGET_DLLIMPORT_DECL_ATTRIBUTES
static tree arm_handle_notshared_attribute (tree *, tree, tree, int, bool *);
+#endif
static void arm_output_function_epilogue (FILE *, HOST_WIDE_INT);
static void arm_output_function_prologue (FILE *, HOST_WIDE_INT);
static void thumb_output_function_prologue (FILE *, HOST_WIDE_INT);
@@ -144,6 +146,9 @@ static rtx arm_expand_binop_builtin (enum insn_code, tree, rtx);
static rtx arm_expand_unop_builtin (enum insn_code, tree, rtx, int);
static rtx arm_expand_builtin (tree, rtx, rtx, enum machine_mode, int);
static void emit_constant_insn (rtx cond, rtx pattern);
+static bool arm_cannot_copy_insn_p (rtx);
+
+static rtx load_tls_operand (rtx, rtx);
#ifdef OBJECT_FORMAT_ELF
static void arm_elf_asm_constructor (rtx, int);
@@ -151,6 +156,9 @@ static void arm_elf_asm_constructor (rtx, int);
#ifndef ARM_PE
static void arm_encode_section_info (tree, rtx, int);
#endif
+
+static void arm_file_end (void);
+
#ifdef AOF_ASSEMBLER
static void aof_globalize_label (FILE *, const char *);
static void aof_dump_imports (FILE *);
@@ -176,6 +184,9 @@ static const char * arm_cxx_unwind_resume_name (void);
static bool arm_cxx_use_aeabi_atexit (void);
static void arm_init_libfuncs (void);
+static bool arm_return_in_msb (tree);
+static rtx arm_dwarf_register_span (rtx);
+
/* Initialize the GCC target structure. */
#if TARGET_DLLIMPORT_DECL_ATTRIBUTES
@@ -186,6 +197,9 @@ static void arm_init_libfuncs (void);
#undef TARGET_ATTRIBUTE_TABLE
#define TARGET_ATTRIBUTE_TABLE arm_attribute_table
+#undef TARGET_ASM_FILE_END
+#define TARGET_ASM_FILE_END arm_file_end
+
#ifdef AOF_ASSEMBLER
#undef TARGET_ASM_BYTE_OP
#define TARGET_ASM_BYTE_OP "\tDCB\t"
@@ -311,6 +325,23 @@ static void arm_init_libfuncs (void);
#define TARGET_EH_FNSPEC_TTABLE_INDIRECT hook_bool_void_false
#endif
+#undef TARGET_RETURN_IN_MSB
+#define TARGET_RETURN_IN_MSB arm_return_in_msb
+
+#undef TARGET_CANNOT_COPY_INSN_P
+#define TARGET_CANNOT_COPY_INSN_P arm_cannot_copy_insn_p
+
+#ifdef HAVE_AS_TLS
+#undef TARGET_HAVE_TLS
+#define TARGET_HAVE_TLS true
+#endif
+
+#undef TARGET_CANNOT_FORCE_CONST_MEM
+#define TARGET_CANNOT_FORCE_CONST_MEM arm_tls_operand_p
+
+#undef TARGET_DWARF_REGISTER_SPAN
+#define TARGET_DWARF_REGISTER_SPAN arm_dwarf_register_span
+
struct gcc_target targetm = TARGET_INITIALIZER;
/* Obstack for minipool constant handling. */
@@ -363,10 +394,19 @@ const char * target_float_switch = NULL;
/* Set by the -mabi=... option. */
const char * target_abi_name = NULL;
+/* Set by the -mtp=... option. */
+const char * target_thread_switch = NULL;
+
+enum arm_tp_type target_thread_pointer;
+
/* Used to parse -mstructure_size_boundary command line option. */
const char * structure_size_string = NULL;
int arm_structure_size_boundary = DEFAULT_STRUCTURE_SIZE_BOUNDARY;
+/* Used for Thumb call_via trampolines. */
+rtx thumb_call_via_label[13];
+static int thumb_call_reg_needed;
+
/* Bit values used to identify processor capabilities. */
#define FL_CO_PROC (1 << 0) /* Has external co-processor bus */
#define FL_ARCH3M (1 << 1) /* Extended multiply */
@@ -462,7 +502,7 @@ enum machine_mode output_memory_reference_mode;
/* The register number to be used for the PIC offset register. */
const char * arm_pic_register_string = NULL;
-int arm_pic_register = INVALID_REGNUM;
+unsigned int arm_pic_register = INVALID_REGNUM;
/* Set to 1 when a return insn is output, this means that the epilogue
is not needed. */
@@ -623,7 +663,8 @@ static const struct abi_name arm_all_abis[] =
{"apcs-gnu", ARM_ABI_APCS},
{"atpcs", ARM_ABI_ATPCS},
{"aapcs", ARM_ABI_AAPCS},
- {"iwmmxt", ARM_ABI_IWMMXT}
+ {"iwmmxt", ARM_ABI_IWMMXT},
+ {"aapcs-linux", ARM_ABI_AAPCS_LINUX}
};
/* Return the number of bits set in VALUE. */
@@ -737,6 +778,13 @@ arm_init_libfuncs (void)
set_optab_libfunc (udiv_optab, DImode, "__aeabi_uldivmod");
set_optab_libfunc (sdiv_optab, SImode, "__aeabi_idivmod");
set_optab_libfunc (udiv_optab, SImode, "__aeabi_uidivmod");
+
+ /* We don't have mod libcalls. Fortunately gcc knows how to use the
+ divmod libcalls instead. */
+ set_optab_libfunc (smod_optab, DImode, NULL);
+ set_optab_libfunc (umod_optab, DImode, NULL);
+ set_optab_libfunc (smod_optab, SImode, NULL);
+ set_optab_libfunc (umod_optab, SImode, NULL);
}
/* Fix up any incompatible options that the user has specified.
@@ -1095,9 +1143,30 @@ arm_override_options (void)
|| arm_fpu_tune == FPUTYPE_FPA_EMU3)
&& (tune_flags & FL_MODE32) == 0)
flag_schedule_insns = flag_schedule_insns_after_reload = 0;
-
+
+ /* Default to the appropriate thread pointer access method. */
+ if (arm_abi == ARM_ABI_AAPCS_LINUX)
+ target_thread_pointer = TP_LINUX;
+ else
+ target_thread_pointer = TP_SOFT;
+
+ if (target_thread_switch)
+ {
+ if (strcmp (target_thread_switch, "soft") == 0)
+ target_thread_pointer = TP_SOFT;
+ else if (strcmp (target_thread_switch, "cp15") == 0)
+ target_thread_pointer = TP_CP15;
+ else if (strcmp (target_thread_switch, "linux") == 0)
+ target_thread_pointer = TP_LINUX;
+ else
+ error ("invalid thread pointer option: -mtp=%s", target_thread_switch);
+ }
+
+ if (TARGET_HARD_TP && TARGET_THUMB)
+ error ("can not use -mtp=cp15 with -mthumb");
+
/* Override the default structure alignment for AAPCS ABI. */
- if (arm_abi == ARM_ABI_AAPCS)
+ if (TARGET_AAPCS_BASED)
arm_structure_size_boundary = 8;
if (structure_size_string != NULL)
@@ -1251,7 +1320,9 @@ arm_compute_func_type (void)
register values that will never be needed again. This optimization
was added to speed up context switching in a kernel application. */
if (optimize > 0
- && (TREE_NOTHROW (current_function_decl) || !flag_exceptions)
+ && (TREE_NOTHROW (current_function_decl)
+ || !(flag_unwind_tables
+ || (flag_exceptions && !USING_SJLJ_EXCEPTIONS)))
&& TREE_THIS_VOLATILE (current_function_decl))
type |= ARM_FT_VOLATILE;
@@ -2254,6 +2325,17 @@ arm_canonicalize_comparison (enum rtx_code code, rtx * op1)
return code;
}
+/* Values which must be returned in the most-significant end of the return
+ register. */
+
+static bool
+arm_return_in_msb (tree valtype)
+{
+ return (TARGET_AAPCS_BASED
+ && BYTES_BIG_ENDIAN
+ && (AGGREGATE_TYPE_P (valtype)
+ || TREE_CODE (valtype) == COMPLEX_TYPE));
+}
/* Define how to find the value returned by a function. */
@@ -2263,11 +2345,23 @@ rtx arm_function_value(tree type, tree func ATTRIBUTE_UNUSED)
int unsignedp ATTRIBUTE_UNUSED;
rtx r ATTRIBUTE_UNUSED;
-
mode = TYPE_MODE (type);
/* Promote integer types. */
if (INTEGRAL_TYPE_P (type))
PROMOTE_FUNCTION_MODE (mode, unsignedp, type);
+
+ /* Promotes small structs returned in a register to full-word size
+ * for big-endian AAPCS. */
+ if (arm_return_in_msb (type))
+ {
+ HOST_WIDE_INT size = int_size_in_bytes (type);
+ if (size % UNITS_PER_WORD != 0)
+ {
+ size += UNITS_PER_WORD - size % UNITS_PER_WORD;
+ mode = mode_for_size (size * BITS_PER_UNIT, MODE_INT, 0);
+ }
+ }
+
return LIBCALL_VALUE(mode);
}
@@ -2380,6 +2474,7 @@ arm_return_in_memory (tree type)
return 1;
}
+
/* Indicate whether or not words of a double are in big-endian order. */
int
@@ -2565,6 +2660,72 @@ arm_va_arg (tree valist, tree type)
return std_expand_builtin_va_arg (valist, type);
}
+
+/* Return true if a type must be passed in memory. The default definition
+ doesn't allow small aggregates (padded to the size of a word) to be passed
+ in a register, which is required for AAPCS. */
+
+bool
+arm_must_pass_in_stack (enum machine_mode mode, tree type)
+{
+ if (!TARGET_AAPCS_BASED)
+ return default_must_pass_in_stack (mode, type);
+
+ if (!type)
+ return false;
+
+ /* If the type has variable size... */
+ if (TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
+ return true;
+
+ /* If the type is marked as addressable (it is required
+ to be constructed into the stack)... */
+ if (TREE_ADDRESSABLE (type))
+ return true;
+
+ return false;
+}
+
+
+/* For use by FUNCTION_ARG_PADDING (MODE, TYPE).
+ * Return true if an argument passed on the stack should be padded upwards,
+ * i.e. if the least-significant byte has useful data. */
+
+bool
+arm_pad_arg_upward (enum machine_mode mode, tree type)
+{
+ if (!TARGET_AAPCS_BASED)
+ return DEFAULT_FUNCTION_ARG_PADDING(mode, type);
+
+ if (type && BYTES_BIG_ENDIAN && INTEGRAL_TYPE_P (type))
+ return false;
+
+ return true;
+}
+
+
+/* Similarly, for use by BLOCK_REG_PADDING (MODE, TYPE, FIRST).
+ * For non-AAPCS, return !BYTES_BIG_ENDIAN if the least significant
+ * byte of the register has useful data, and return the opposite if the
+ * most significant byte does.
+ * For AAPCS, small aggregates and small complex types are always padded
+ * upwards. */
+
+bool
+arm_pad_reg_upward (enum machine_mode mode ATTRIBUTE_UNUSED,
+ tree type, int first ATTRIBUTE_UNUSED)
+{
+ if (TARGET_AAPCS_BASED
+ && BYTES_BIG_ENDIAN
+ && (AGGREGATE_TYPE_P (type) || TREE_CODE (type) == COMPLEX_TYPE)
+ && int_size_in_bytes (type) <= 4)
+ return true;
+
+ /* Otherwise, use default padding. */
+ return !BYTES_BIG_ENDIAN;
+}
+
+
/* Encode the current state of the #pragma [no_]long_calls. */
typedef enum
@@ -2705,6 +2866,7 @@ arm_handle_isr_attribute (tree *node, tree name, tree args, int flags,
return NULL_TREE;
}
+#if TARGET_DLLIMPORT_DECL_ATTRIBUTES
/* Handle the "notshared" attribute. This attribute is another way of
requesting hidden visibility. ARM's compiler supports
"__declspec(notshared)"; we support the same thing via an
@@ -2727,6 +2889,7 @@ arm_handle_notshared_attribute (tree *node,
}
return NULL_TREE;
}
+#endif
/* Return 0 if the attributes for two types are incompatible, 1 if they
are compatible, and 2 if they are nearly compatible (which causes a
@@ -3016,6 +3179,9 @@ legitimize_pic_address (rtx orig, enum machine_mode mode, rtx reg)
&& XEXP (XEXP (orig, 0), 0) == pic_offset_table_rtx)
return orig;
+ if (GET_CODE (XEXP (orig, 0)) == UNSPEC)
+ return orig;
+
if (reg == 0)
{
if (no_new_pseudos)
@@ -3163,6 +3329,24 @@ arm_address_register_rtx_p (rtx x, int strict_p)
|| regno == ARG_POINTER_REGNUM);
}
+/* Return TRUE if this rtx is the difference of a symbol and a label,
+ and will reduce to a PC-relative relocation in the object file.
+ Expressions like this can be left alone when generating PIC, rather
+ than forced through the GOT. */
+static int
+pcrel_constant_p (rtx x)
+{
+ if (GET_CODE (x) == MINUS)
+ return symbol_mentioned_p (XEXP (x, 0)) && label_mentioned_p (XEXP (x, 1));
+
+ if (GET_CODE (x) == UNSPEC
+ && XINT (x, 1) == UNSPEC_TLS
+ && INTVAL (XVECEXP (x, 0, 1)) == TLS_MODEL_LOCAL_EXEC)
+ return 1; /* This is actually an offset from $tp. */
+
+ return FALSE;
+}
+
/* Return nonzero if X is a valid ARM state address operand. */
int
arm_legitimate_address_p (enum machine_mode mode, rtx x, RTX_CODE outer,
@@ -3240,8 +3424,10 @@ arm_legitimate_address_p (enum machine_mode mode, rtx x, RTX_CODE outer,
else if (GET_MODE_CLASS (mode) != MODE_FLOAT
&& code == SYMBOL_REF
&& CONSTANT_POOL_ADDRESS_P (x)
+ && ! tls_symbolic_operand (x, VOIDmode)
&& ! (flag_pic
- && symbol_mentioned_p (get_pool_constant (x))))
+ && (symbol_mentioned_p (get_pool_constant (x))
+ && ! pcrel_constant_p (get_pool_constant (x)))))
return 1;
return 0;
@@ -3404,7 +3590,7 @@ thumb_legitimate_address_p (enum machine_mode mode, rtx x, int strict_p)
/* This is PC relative data before arm_reorg runs. */
else if (GET_MODE_SIZE (mode) >= 4 && CONSTANT_P (x)
&& GET_CODE (x) == SYMBOL_REF
- && CONSTANT_POOL_ADDRESS_P (x) && ! flag_pic)
+ && CONSTANT_POOL_ADDRESS_P (x) && ! flag_pic && ! tls_symbolic_operand (x, VOIDmode))
return 1;
/* This is PC relative data after arm_reorg runs. */
@@ -3466,8 +3652,10 @@ thumb_legitimate_address_p (enum machine_mode mode, rtx x, int strict_p)
&& GET_MODE_SIZE (mode) == 4
&& GET_CODE (x) == SYMBOL_REF
&& CONSTANT_POOL_ADDRESS_P (x)
- && !(flag_pic
- && symbol_mentioned_p (get_pool_constant (x))))
+ && ! tls_symbolic_operand (x, VOIDmode)
+ && ! (flag_pic
+ && (symbol_mentioned_p (get_pool_constant (x))
+ && ! pcrel_constant_p (get_pool_constant (x)))))
return 1;
return 0;
@@ -3493,11 +3681,151 @@ thumb_legitimate_offset_p (enum machine_mode mode, HOST_WIDE_INT val)
}
}
+/* Build the SYMBOL_REF for __tls_get_addr. */
+
+static GTY(()) rtx tls_get_addr_libfunc;
+
+static rtx
+get_tls_get_addr (void)
+{
+ if (!tls_get_addr_libfunc)
+ tls_get_addr_libfunc = init_one_libfunc ("__tls_get_addr");
+ return tls_get_addr_libfunc;
+}
+
+static rtx
+arm_load_tp (rtx target)
+{
+ if (TARGET_HARD_TP)
+ {
+ /* Can return in any reg. */
+ if (!target)
+ target = gen_reg_rtx (SImode);
+
+ emit_insn (gen_load_tp_hard (target));
+ }
+ else if (TARGET_LINUX_TP)
+ {
+ rtx tp;
+
+ /* Can return in any reg. */
+ if (!target)
+ target = gen_reg_rtx (SImode);
+
+ tp = gen_rtx_MEM (Pmode, gen_int_mode (0xffff0ffc, Pmode));
+ RTX_UNCHANGING_P (tp) = 1;
+ emit_move_insn (target, tp);
+ }
+ else
+ {
+ /* Always returned in R0 */
+ target = gen_rtx_REG (SImode, 0);
+
+ emit_insn (gen_load_tp_soft (target));
+ }
+ return target;
+}
+
+/* Load a TLS operand from memory. */
+static rtx
+load_tls_operand (rtx x, rtx reg)
+{
+ rtx tmp;
+
+ if (reg == NULL_RTX)
+ reg = gen_reg_rtx (SImode);
+
+ tmp = gen_rtx_CONST (SImode, x);
+
+ emit_move_insn (reg, tmp);
+
+ return reg;
+}
+
+rtx
+legitimize_tls_address (rtx x, unsigned int model, rtx reg)
+{
+ rtx dest, tp, tmp, label, dummy_label, sum, insn;
+
+ switch (model)
+ {
+ case TLS_MODEL_LOCAL_DYNAMIC: /* XXX */
+ case TLS_MODEL_GLOBAL_DYNAMIC:
+ label = gen_label_rtx ();
+ dummy_label = gen_label_rtx ();
+ LABEL_PRESERVE_P (dummy_label) = 1;
+ LABEL_NUSES (dummy_label) = 1;
+
+ sum = gen_rtx_UNSPEC (Pmode,
+ gen_rtvec (4, x, GEN_INT (model),
+ gen_rtx_LABEL_REF (Pmode, label),
+ GEN_INT (TARGET_ARM ? 8 : 4)),
+ UNSPEC_TLS);
+ reg = load_tls_operand (sum, reg);
+
+ if (TARGET_ARM)
+ insn = emit_insn (gen_pic_add_dot_plus_eight (reg, label));
+ else
+ insn = emit_insn (gen_pic_add_dot_plus_four (reg, label));
+
+ emit_label_before (dummy_label, insn);
+
+ return emit_library_call_value (get_tls_get_addr (), 0, LCT_PURE,
+ Pmode, 1, reg, Pmode);
+
+ case TLS_MODEL_INITIAL_EXEC:
+ label = gen_label_rtx ();
+ dummy_label = gen_label_rtx ();
+ LABEL_PRESERVE_P (dummy_label) = 1;
+ LABEL_NUSES (dummy_label) = 1;
+
+ sum = gen_rtx_UNSPEC (Pmode,
+ gen_rtvec (4, x, GEN_INT (model),
+ gen_rtx_LABEL_REF (Pmode, label),
+ GEN_INT (TARGET_ARM ? 8 : 4)),
+ UNSPEC_TLS);
+ reg = load_tls_operand (sum, reg);
+
+ if (TARGET_ARM)
+ insn = emit_insn (gen_tls_load_dot_plus_eight (reg, reg, label, dummy_label));
+ else
+ insn = emit_insn (gen_tls_load_dot_plus_four (reg, reg, label, dummy_label));
+
+ emit_label_before (dummy_label, insn);
+
+ tp = arm_load_tp (NULL_RTX);
+
+ return gen_rtx_PLUS (Pmode, tp, reg);
+
+ case TLS_MODEL_LOCAL_EXEC:
+ tp = arm_load_tp (NULL_RTX);
+
+ tmp = gen_rtx_UNSPEC (Pmode,
+ gen_rtvec (2, x, GEN_INT (model)),
+ UNSPEC_TLS);
+
+ reg = force_reg (SImode, gen_rtx_CONST (SImode, tmp));
+
+ return gen_rtx_PLUS (Pmode, tp, reg);
+
+ default:
+ abort ();
+ }
+
+ return dest;
+}
+
/* Try machine-dependent ways of modifying an illegitimate address
to be legitimate. If we find one, return the new, valid address. */
rtx
arm_legitimize_address (rtx x, rtx orig_x, enum machine_mode mode)
{
+ unsigned tls;
+
+ tls = tls_symbolic_operand (x, mode);
+ if (tls)
+ return legitimize_tls_address (x, tls, NULL_RTX);
+
if (GET_CODE (x) == PLUS)
{
rtx xop0 = XEXP (x, 0);
@@ -3577,6 +3905,51 @@ arm_legitimize_address (rtx x, rtx orig_x, enum machine_mode mode)
return x;
}
+rtx
+thumb_legitimize_address (rtx x, rtx orig_x ATTRIBUTE_UNUSED, enum machine_mode mode)
+{
+ unsigned tls;
+
+ tls = tls_symbolic_operand (x, mode);
+ if (tls)
+ return legitimize_tls_address (x, tls, NULL_RTX);
+
+ if (flag_pic)
+ return legitimize_pic_address (x, mode, NULL_RTX);
+
+ return x;
+}
+
+/* Test for various thread-local symbols. */
+
+/* Return 1 if X is a thread-local symbol. */
+
+bool
+arm_tls_operand_p (rtx x)
+{
+ if (! TARGET_HAVE_TLS)
+ return false;
+
+ return tls_symbolic_operand (x, SImode);
+}
+
+int
+tls_symbolic_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
+{
+ if (GET_CODE (op) != SYMBOL_REF)
+ return 0;
+ return SYMBOL_REF_TLS_MODEL (op);
+}
+
+/* Valid input to a move instruction. */
+int
+move_input_operand (rtx op, enum machine_mode mode)
+{
+ if (tls_symbolic_operand (op, mode))
+ return 0;
+ return general_operand (op, mode);
+}
+
#define REG_OR_SUBREG_REG(X) \
@@ -5309,6 +5682,47 @@ label_mentioned_p (rtx x)
return 0;
}
+int
+tls_mentioned_p (rtx x)
+{
+ switch (GET_CODE (x))
+ {
+ case CONST:
+ return tls_mentioned_p (XEXP (x, 0));
+
+ case UNSPEC:
+ if (XINT (x, 1) == UNSPEC_TLS)
+ return 1;
+
+ default:
+ return 0;
+ }
+}
+
+/* Must not copy a SET whose source operand is PC-relative. */
+
+bool
+arm_cannot_copy_insn_p (rtx insn)
+{
+ if (INSN_P (insn))
+ {
+ rtx pat = PATTERN (insn);
+
+ if (GET_CODE (pat) == PARALLEL
+ && GET_CODE (XVECEXP (pat, 0, 0)) == SET)
+ {
+ rtx rhs = SET_SRC (XVECEXP (pat, 0, 0));
+
+ if (GET_CODE (rhs) == MEM
+ && GET_CODE (XEXP (rhs, 0)) == UNSPEC
+ && XINT (XEXP (rhs, 0), 1) == UNSPEC_PIC_BASE)
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
enum rtx_code
minmax_code (rtx x)
{
@@ -9956,6 +10370,23 @@ arm_output_function_epilogue (FILE *file ATTRIBUTE_UNUSED,
if (TARGET_THUMB)
{
+ int regno;
+
+ /* Emit any call-via-reg trampolines that are needed for v4t support
+ of call_reg and call_value_reg type insns. */
+ for (regno = 0; regno < SP_REGNUM; regno++)
+ {
+ rtx label = cfun->machine->call_via[regno];
+
+ if (label != NULL)
+ {
+ function_section (current_function_decl);
+ targetm.asm_out.internal_label (asm_out_file, "L",
+ CODE_LABEL_NUMBER (label));
+ asm_fprintf (asm_out_file, "\tbx\t%r\n", regno);
+ }
+ }
+
/* ??? Probably not safe to set this here, since it assumes that a
function will be emitted as assembly immediately after we generate
RTL for it. This does not happen for inline functions. */
@@ -11683,6 +12114,9 @@ arm_hard_regno_mode_ok (unsigned int regno, enum machine_mode mode)
int
arm_regno_class (int regno)
{
+ if (regno == 0)
+ return RETURN_REG;
+
if (TARGET_THUMB)
{
if (regno == STACK_POINTER_REGNUM)
@@ -12265,8 +12699,23 @@ arm_init_iwmmxt_builtins (void)
}
static void
+arm_init_tls_builtins (void)
+{
+ tree ftype;
+ tree nothrow = tree_cons (get_identifier ("nothrow"), NULL, NULL);
+ tree const_nothrow = tree_cons (get_identifier ("const"), NULL, nothrow);
+
+ ftype = build_function_type (ptr_type_node, void_list_node);
+ builtin_function ("__builtin_thread_pointer", ftype,
+ ARM_BUILTIN_THREAD_POINTER, BUILT_IN_MD,
+ NULL, const_nothrow);
+}
+
+static void
arm_init_builtins (void)
{
+ arm_init_tls_builtins ();
+
if (TARGET_REALLY_IWMMXT)
arm_init_iwmmxt_builtins ();
}
@@ -12574,6 +13023,9 @@ arm_expand_builtin (tree exp,
emit_insn (gen_iwmmxt_clrdi (target));
return target;
+ case ARM_BUILTIN_THREAD_POINTER:
+ return arm_load_tp (target);
+
default:
break;
}
@@ -13977,6 +14429,38 @@ thumb_output_move_mem_multiple (int n, rtx *operands)
return "";
}
+/* Output a call-via instruction for thumb state. */
+const char *
+thumb_call_via_reg (rtx reg)
+{
+ int regno = REGNO (reg);
+ rtx *labelp;
+
+ if (regno >= SP_REGNUM)
+ abort ();
+
+ /* If we are in the normal text section we can use a single instance
+ per compilation unit. If we are doing function sections, then we need
+ an entry per section, since we can't rely on reachability. */
+ if (in_text_section ())
+ {
+ thumb_call_reg_needed = 1;
+
+ if (thumb_call_via_label[regno] == NULL)
+ thumb_call_via_label[regno] = gen_label_rtx ();
+ labelp = thumb_call_via_label + regno;
+ }
+ else
+ {
+ if (cfun->machine->call_via[regno] == NULL)
+ cfun->machine->call_via[regno] = gen_label_rtx ();
+ labelp = cfun->machine->call_via + regno;
+ }
+
+ output_asm_insn ("bl\t%a0", labelp);
+ return "";
+}
+
/* Routines for generating rtl. */
void
thumb_expand_movstrqi (rtx *operands)
@@ -14123,6 +14607,31 @@ arm_asm_output_labelref (FILE *stream, const char *name)
asm_fprintf (stream, "%U%s", name);
}
+static void
+arm_file_end (void)
+{
+ int regno;
+
+ if (! thumb_call_reg_needed)
+ return;
+
+ text_section ();
+ asm_fprintf (asm_out_file, "\t.code 16\n");
+ ASM_OUTPUT_ALIGN (asm_out_file, 1);
+
+ for (regno = 0; regno < SP_REGNUM; regno++)
+ {
+ rtx label = thumb_call_via_label[regno];
+
+ if (label != 0)
+ {
+ targetm.asm_out.internal_label (asm_out_file, "L",
+ CODE_LABEL_NUMBER (label));
+ asm_fprintf (asm_out_file, "\tbx\t%r\n", regno);
+ }
+ }
+}
+
rtx aof_pic_label;
#ifdef AOF_ASSEMBLER
@@ -14319,6 +14828,7 @@ aof_file_end (void)
{
if (flag_pic)
aof_dump_pic_table (asm_out_file);
+ arm_file_end ();
aof_dump_imports (asm_out_file);
fputs ("\tEND\n", asm_out_file);
}
@@ -14352,6 +14862,8 @@ arm_encode_section_info (tree decl, rtx rtl, int first)
else if (! TREE_PUBLIC (decl))
arm_encode_call_attribute (decl, SHORT_CALL_FLAG_CHAR);
}
+
+ default_encode_section_info (decl, rtl, first);
}
#endif /* !ARM_PE */
@@ -15060,3 +15572,105 @@ arm_cxx_unwind_resume_name (void)
#endif
return default_unwind_resume_name ();
}
+
+
+static bool
+arm_emit_tls_decoration (FILE *fp, rtx x)
+{
+ int model;
+ rtx val;
+
+ val = XVECEXP (x, 0, 0);
+ model = INTVAL (XVECEXP (x, 0, 1));
+
+ output_addr_const (fp, val);
+
+ switch (model)
+ {
+ case TLS_MODEL_GLOBAL_DYNAMIC:
+ case TLS_MODEL_LOCAL_DYNAMIC: /* XXX */
+ fputs ("(tlsgd)", fp);
+ break;
+ case TLS_MODEL_INITIAL_EXEC:
+ fputs ("(gottpoff)", fp);
+ break;
+ case TLS_MODEL_LOCAL_EXEC:
+ fputs ("(tpoff)", fp);
+ break;
+ default:
+ abort ();
+ }
+
+ switch (model)
+ {
+ case TLS_MODEL_GLOBAL_DYNAMIC:
+ case TLS_MODEL_LOCAL_DYNAMIC: /* XXX */
+ case TLS_MODEL_INITIAL_EXEC:
+ fputs (" + (. - ", fp);
+ output_addr_const (fp, XVECEXP (x, 0, 2));
+ fputs (" - ", fp);
+ output_addr_const (fp, XVECEXP (x, 0, 3));
+ fputc (')', fp);
+ break;
+ }
+
+ return TRUE;
+}
+
+bool
+arm_output_addr_const_extra (FILE *fp, rtx x)
+{
+ if (GET_CODE (x) == UNSPEC && XINT (x, 1) == UNSPEC_TLS)
+ return arm_emit_tls_decoration (fp, x);
+ else if (GET_CODE (x) == CONST_VECTOR)
+ return arm_emit_vector_const (fp, x);
+
+ return FALSE;
+}
+
+
+/* Map internal gcc register numbers to DWARF2 register numbers. */
+
+unsigned int
+arm_dbx_register_number (unsigned int regno)
+{
+ if (regno < 16)
+ return regno;
+
+ /* TODO: Legacy targets output FPA regs as registers 16-23 for backwards
+ compatibility. The EABI defines them as registers 96-103. */
+ if (IS_FPA_REGNUM (regno))
+ return (TARGET_AAPCS_BASED ? 96 : 16) + regno - FIRST_FPA_REGNUM;
+
+ if (IS_VFP_REGNUM (regno))
+ return 64 + regno - FIRST_VFP_REGNUM;
+
+ if (IS_IWMMXT_GR_REGNUM (regno))
+ return 104 + regno - FIRST_IWMMXT_GR_REGNUM;
+
+ if (IS_IWMMXT_REGNUM (regno))
+ return 112 + regno - FIRST_IWMMXT_REGNUM;
+
+ abort ();
+}
+
+
+/* Double precision VFP registers are referenced by a single DWARF register,
+ even though they cover two gcc registers. Return the REG rtx so that gcc
+ doesn't ouptu DW_OP_piece for these. */
+
+static rtx
+arm_dwarf_register_span (rtx reg)
+{
+ unsigned regno;
+
+ regno = REGNO (reg);
+ /* We could return NULL for single precision values, but it's safe
+ (and easier) to return the REG all the time. */
+ if (IS_VFP_REGNUM (regno))
+ return reg;
+
+ return NULL;
+}
+
+#include "gt-arm.h"
diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h
index 36f91b39817..364b04ab884 100644
--- a/gcc/config/arm/arm.h
+++ b/gcc/config/arm/arm.h
@@ -1,6 +1,6 @@
/* Definitions of target machine for GNU compiler, for ARM.
Copyright (C) 1991, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
- 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+ 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
Contributed by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl)
and Martin Simmons (@harleqn.co.uk).
More major hacks by Richard Earnshaw (rearnsha@arm.com)
@@ -127,6 +127,8 @@ extern const char *target_fpe_name;
extern const char *target_float_abi_name;
/* For -m{soft,hard}-float. */
extern const char *target_float_switch;
+/* For -mtp={soft,cp15,linux}. */
+extern const char *target_thread_switch;
/* Which ABI to use. */
extern const char *target_abi_name;
/* Define the information needed to generate branch insns. This is
@@ -297,6 +299,10 @@ extern GTY(()) rtx aof_pic_label;
#define TARGET_AAPCS_BASED \
(arm_abi != ARM_ABI_APCS && arm_abi != ARM_ABI_ATPCS)
+#define TARGET_HARD_TP (target_thread_pointer == TP_CP15)
+#define TARGET_SOFT_TP (target_thread_pointer == TP_SOFT)
+#define TARGET_LINUX_TP (target_thread_pointer == TP_LINUX)
+
/* True iff the full BPABI is being used. If TARGET_BPABI is true,
then TARGET_AAPCS_BASED must be true -- but the converse does not
hold. TARGET_BPABI implies the use of the BPABI runtime library,
@@ -396,7 +402,9 @@ extern GTY(()) rtx aof_pic_label;
{"soft-float", &target_float_switch, \
N_("Alias for -mfloat-abi=soft"), "s"}, \
{"hard-float", &target_float_switch, \
- N_("Alias for -mfloat-abi=hard"), "h"} \
+ N_("Alias for -mfloat-abi=hard"), "h"}, \
+ {"tp=", &target_thread_switch, \
+ N_("Specify how to access the thread pointer"), 0} \
}
/* Support for a compile-time default CPU, et cetera. The rules are:
@@ -490,7 +498,8 @@ enum arm_abi_type
ARM_ABI_APCS,
ARM_ABI_ATPCS,
ARM_ABI_AAPCS,
- ARM_ABI_IWMMXT
+ ARM_ABI_IWMMXT,
+ ARM_ABI_AAPCS_LINUX
};
extern enum arm_abi_type arm_abi;
@@ -499,6 +508,15 @@ extern enum arm_abi_type arm_abi;
#define ARM_DEFAULT_ABI ARM_ABI_APCS
#endif
+/* Which thread pointer access sequence to use. */
+enum arm_tp_type {
+ TP_SOFT,
+ TP_CP15,
+ TP_LINUX
+};
+
+extern enum arm_tp_type target_thread_pointer;
+
/* Nonzero if this chip supports the ARM Architecture 3M extensions. */
extern int arm_arch3m;
@@ -607,9 +625,10 @@ extern int arm_is_6_or_7;
#define PROMOTE_FUNCTION_ARGS
#define PROMOTE_FUNCTION_MODE(MODE, UNSIGNEDP, TYPE) \
- if (GET_MODE_CLASS (MODE) == MODE_INT \
- && GET_MODE_SIZE (MODE) < 4) \
- (MODE) = SImode; \
+ if ((GET_MODE_CLASS (MODE) == MODE_INT \
+ || GET_MODE_CLASS (MODE) == MODE_COMPLEX_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. */
@@ -715,8 +734,12 @@ extern const char * structure_size_string;
#define SIZE_TYPE (TARGET_AAPCS_BASED ? "unsigned int" : "long unsigned int")
#endif
+#ifndef PTRDIFF_TYPE
+#define PTRDIFF_TYPE (TARGET_AAPCS_BASED ? "int" : "long int")
+#endif
+
#ifndef DEFAULT_SHORT_ENUMS
-#define DEFAULT_SHORT_ENUMS TARGET_AAPCS_BASED
+#define DEFAULT_SHORT_ENUMS (TARGET_AAPCS_BASED && arm_abi != ARM_ABI_AAPCS_LINUX)
#endif
/* AAPCS requires that structure alignment is affected by bitfields. */
@@ -904,7 +927,7 @@ extern const char * structure_size_string;
scratch registers. */ \
for (regno = FIRST_IWMMXT_GR_REGNUM; \
regno <= LAST_IWMMXT_GR_REGNUM; ++ regno) \
- fixed_regs[regno] = call_used_regs[regno] = 0; \
+ fixed_regs[regno] = 0; \
/* The XScale ABI has wR0 - wR9 as scratch registers, \
the rest as call-preserved registers. */ \
for (regno = FIRST_IWMMXT_REGNUM; \
@@ -1047,6 +1070,8 @@ extern const char * structure_size_string;
/* ARM floating pointer registers. */
#define FIRST_FPA_REGNUM 16
#define LAST_FPA_REGNUM 23
+#define IS_FPA_REGNUM(REGNUM) \
+ (((REGNUM) >= FIRST_FPA_REGNUM) && ((REGNUM) <= LAST_FPA_REGNUM))
#define FIRST_IWMMXT_GR_REGNUM 43
#define LAST_IWMMXT_GR_REGNUM 46
@@ -1079,6 +1104,8 @@ extern const char * structure_size_string;
/* VFP adds 32 + 1 more. */
#define FIRST_PSEUDO_REGISTER 96
+#define DBX_REGISTER_NUMBER(REGNO) arm_dbx_register_number (REGNO)
+
/* Value should be nonzero if functions must have frame pointers.
Zero means the frame pointer need not be set up (and parms may be accessed
via the stack pointer) in functions that seem suitable.
@@ -1165,6 +1192,7 @@ enum reg_class
VFP_REGS,
IWMMXT_GR_REGS,
IWMMXT_REGS,
+ RETURN_REG,
LO_REGS,
STACK_REG,
BASE_REGS,
@@ -1187,6 +1215,7 @@ enum reg_class
"VFP_REGS", \
"IWMMXT_GR_REGS", \
"IWMMXT_REGS", \
+ "RETURN_REG", \
"LO_REGS", \
"STACK_REG", \
"BASE_REGS", \
@@ -1208,6 +1237,7 @@ enum reg_class
{ 0x00000000, 0x80000000, 0x7FFFFFFF }, /* VFP_REGS */ \
{ 0x00000000, 0x00007800, 0x00000000 }, /* IWMMXT_GR_REGS */ \
{ 0x00000000, 0x7FFF8000, 0x00000000 }, /* IWMMXT_REGS */ \
+ { 0x00000001, 0x00000000, 0x00000000 }, /* RETURN_REG */ \
{ 0x000000FF, 0x00000000, 0x00000000 }, /* LO_REGS */ \
{ 0x00002000, 0x00000000, 0x00000000 }, /* STACK_REG */ \
{ 0x000020FF, 0x00000000, 0x00000000 }, /* BASE_REGS */ \
@@ -1269,6 +1299,7 @@ enum reg_class
: (C) == 'y' ? IWMMXT_REGS \
: (C) == 'z' ? IWMMXT_GR_REGS \
: (C) == 'l' ? (TARGET_ARM ? GENERAL_REGS : LO_REGS) \
+ : (C) == 'Z' ? RETURN_REG \
: TARGET_ARM ? NO_REGS \
: (C) == 'h' ? HI_REGS \
: (C) == 'b' ? BASE_REGS \
@@ -1693,9 +1724,16 @@ typedef struct machine_function GTY(())
/* Records if sibcalls are blocked because an argument
register is needed to preserve stack alignment. */
int sibcall_blocked;
+ /* Labels for per-function Thumb call-via stubs. One per potential calling
+ register. We can never call via SP, LR or PC. */
+ rtx call_via[13];
}
machine_function;
+/* As in the machine_function, a global set of call-via labels, for code
+ that is in text_section(). */
+extern GTY(()) rtx thumb_call_via_label[13];
+
/* A C type for declaring a variable that is used as the first argument of
`FUNCTION_ARG' and other related values. For some target machines, the
type `int' suffices and can hold the number of bytes of argument so far. */
@@ -1751,6 +1789,20 @@ typedef struct
#define FUNCTION_ARG_PASS_BY_REFERENCE(CUM, MODE, TYPE, NAMED) \
arm_function_arg_pass_by_reference (&CUM, MODE, TYPE, NAMED)
+#define MUST_PASS_IN_STACK(MODE, TYPE) \
+ arm_must_pass_in_stack (MODE, TYPE)
+
+#define FUNCTION_ARG_PADDING(MODE, TYPE) \
+ (arm_pad_arg_upward (MODE, TYPE) ? upward : downward)
+
+#define BLOCK_REG_PADDING(MODE, TYPE, FIRST) \
+ (arm_pad_reg_upward (MODE, TYPE, FIRST) ? upward : downward)
+
+/* For AAPCS, padding should never be below the argument. For other ABIs,
+ * mimic the default. */
+#define PAD_VARARGS_DOWN \
+ ((TARGET_AAPCS_BASED) ? 0 : BYTES_BIG_ENDIAN)
+
/* Initialize a variable CUM of type CUMULATIVE_ARGS
for a call to a function whose data type is FNTYPE.
For a library call, FNTYPE is 0.
@@ -2083,8 +2135,10 @@ typedef struct
|| CONSTANT_ADDRESS_P (X) \
|| flag_pic)
-#define LEGITIMATE_CONSTANT_P(X) \
- (TARGET_ARM ? ARM_LEGITIMATE_CONSTANT_P (X) : THUMB_LEGITIMATE_CONSTANT_P (X))
+#define LEGITIMATE_CONSTANT_P(X) \
+ (!arm_tls_operand_p (X) \
+ && (TARGET_ARM ? ARM_LEGITIMATE_CONSTANT_P (X) \
+ : THUMB_LEGITIMATE_CONSTANT_P (X)))
/* Special characters prefixed to function names
in order to encode attribute like information.
@@ -2120,10 +2174,14 @@ typedef struct
/* The EABI specifies that constructors should go in .init_array.
Other targets use .ctors for compatibility. */
+#ifndef ARM_EABI_CTORS_SECTION_OP
#define ARM_EABI_CTORS_SECTION_OP \
"\t.section\t.init_array,\"aw\",%init_array"
+#endif
+#ifndef ARM_EABI_DTORS_SECTION_OP
#define ARM_EABI_DTORS_SECTION_OP \
"\t.section\t.fini_array,\"aw\",%fini_array"
+#endif
#define ARM_CTORS_SECTION_OP \
"\t.section\t.ctors,\"aw\",%progbits"
#define ARM_DTORS_SECTION_OP \
@@ -2167,7 +2225,7 @@ typedef struct
#ifdef TARGET_UNWIND_INFO
#define ARM_EABI_UNWIND_TABLES \
- (!USING_SJLJ_EXCEPTIONS && flag_exceptions && flag_unwind_tables)
+ ((!USING_SJLJ_EXCEPTIONS && flag_exceptions) || flag_unwind_tables)
#else
#define ARM_EABI_UNWIND_TABLES 0
#endif
@@ -2270,10 +2328,12 @@ do { \
goto WIN; \
} while (0)
-#define THUMB_LEGITIMIZE_ADDRESS(X, OLDX, MODE, WIN) \
-do { \
- if (flag_pic) \
- (X) = legitimize_pic_address (OLDX, MODE, NULL_RTX); \
+#define THUMB_LEGITIMIZE_ADDRESS(X, OLDX, MODE, WIN) \
+do { \
+ X = thumb_legitimize_address (X, OLDX, MODE); \
+ \
+ if (memory_address_p (MODE, X)) \
+ goto WIN; \
} while (0)
#define LEGITIMIZE_ADDRESS(X, OLDX, MODE, WIN) \
@@ -2383,7 +2443,7 @@ do { \
/* We decide which register to use based on the compilation options and
the assembler in use; this is more general than the APCS restriction of
using sb (r9) all the time. */
-extern int arm_pic_register;
+extern unsigned int arm_pic_register;
/* Used when parsing command line option -mpic-register=. */
extern const char * arm_pic_register_string;
@@ -2395,12 +2455,13 @@ extern const char * arm_pic_register_string;
/* We can't directly access anything that contains a symbol,
nor can we indirect via the constant pool. */
#define LEGITIMATE_PIC_OPERAND_P(X) \
- (!(symbol_mentioned_p (X) \
+ (tls_mentioned_p (X) \
+ || (!(symbol_mentioned_p (X) \
|| label_mentioned_p (X) \
|| (GET_CODE (X) == SYMBOL_REF \
&& CONSTANT_POOL_ADDRESS_P (X) \
&& (symbol_mentioned_p (get_pool_constant (X)) \
- || label_mentioned_p (get_pool_constant (X))))))
+ || label_mentioned_p (get_pool_constant (X)))))))
/* We need to know when we are making a constant pool; this determines
whether data needs to be in the GOT or can be referenced via a GOT
@@ -2677,10 +2738,9 @@ extern int making_const_table;
else \
THUMB_PRINT_OPERAND_ADDRESS (STREAM, X)
-#define OUTPUT_ADDR_CONST_EXTRA(FILE, X, FAIL) \
- if (GET_CODE (X) != CONST_VECTOR \
- || ! arm_emit_vector_const (FILE, X)) \
- goto FAIL;
+#define OUTPUT_ADDR_CONST_EXTRA(file, x, fail) \
+ if (arm_output_addr_const_extra (file, x) == FALSE) \
+ goto fail
/* A C expression whose value is RTL representing the value of the return
address for the frame COUNT steps up from the current frame. */
@@ -2750,6 +2810,8 @@ extern int making_const_table;
{"cirrus_register_operand", {REG}}, \
{"cirrus_fp_register", {REG}}, \
{"cirrus_shift_const", {CONST_INT}}, \
+ {"move_input_operand", {CONST_INT, CONST_DOUBLE, CONST, SYMBOL_REF, \
+ LABEL_REF, SUBREG, REG, MEM, ADDRESSOF}}, \
{"dominant_cc_register", {REG}}, \
{"arm_float_compare_operand", {REG, CONST_DOUBLE}}, \
{"vfp_compare_operand", {REG, CONST_DOUBLE}},
@@ -2923,6 +2985,8 @@ enum arm_builtins
ARM_BUILTIN_WUNPCKELUH,
ARM_BUILTIN_WUNPCKELUW,
+ ARM_BUILTIN_THREAD_POINTER,
+
ARM_BUILTIN_MAX
};
#endif /* ! GCC_ARM_H */
diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md
index 6551a6f6ed7..5aba5105974 100644
--- a/gcc/config/arm/arm.md
+++ b/gcc/config/arm/arm.md
@@ -1,6 +1,6 @@
;;- Machine description for ARM for GNU compiler
;; Copyright 1991, 1993, 1994, 1995, 1996, 1996, 1997, 1998, 1999, 2000,
-;; 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+;; 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
;; Contributed by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl)
;; and Martin Simmons (@harleqn.co.uk).
;; More major hacks by Richard Earnshaw (rearnsha@arm.com).
@@ -87,6 +87,7 @@
(UNSPEC_CLRDI 17) ; Used by the intrinsic form of the iWMMXt CLRDI instruction.
(UNSPEC_WMADDS 18) ; Used by the intrinsic form of the iWMMXt WMADDS instruction.
(UNSPEC_WMADDU 19) ; Used by the intrinsic form of the iWMMXt WMADDU instruction.
+ (UNSPEC_TLS 20) ; A symbol that has been treated properly for TLS usage.
]
)
@@ -1793,7 +1794,7 @@
emit_insn (gen_andsi3 (op1, operands[0], GEN_INT (~mask2)));
emit_insn (gen_iorsi3 (subtarget, op1,
- GEN_INT (op3_value << start_bit)));
+ gen_int_mode (op3_value << start_bit, SImode)));
}
else if (start_bit == 0
&& !(const_ok_for_arm (mask)
@@ -4166,19 +4167,28 @@
operands[1] = force_reg (SImode, operands[1]);
}
}
-
- if (flag_pic
- && (CONSTANT_P (operands[1])
- || symbol_mentioned_p (operands[1])
- || label_mentioned_p (operands[1])))
- operands[1] = legitimize_pic_address (operands[1], SImode,
- (no_new_pseudos ? operands[0] : 0));
+
+ {
+ unsigned long model;
+
+ model = tls_symbolic_operand (operands[1], SImode);
+ if (model)
+ operands[1] = legitimize_tls_address (operands[1], model,
+ (no_new_pseudos ? operands[0] : 0));
+ else if (flag_pic
+ && (CONSTANT_P (operands[1])
+ || symbol_mentioned_p (operands[1])
+ || label_mentioned_p (operands[1]))
+ && ! tls_mentioned_p (operands[1]))
+ operands[1] = legitimize_pic_address (operands[1], SImode,
+ (no_new_pseudos ? operands[0] : 0));
+ }
"
)
(define_insn "*arm_movsi_insn"
[(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r, m")
- (match_operand:SI 1 "general_operand" "rI,K,mi,r"))]
+ (match_operand:SI 1 "move_input_operand" "rI,K,mi,r"))]
"TARGET_ARM && ! TARGET_IWMMXT
&& !(TARGET_HARD_FLOAT && TARGET_VFP)
&& ( register_operand (operands[0], SImode)
@@ -4210,7 +4220,7 @@
(define_insn "*thumb_movsi_insn"
[(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l, m,*lh")
- (match_operand:SI 1 "general_operand" "l, I,J,K,>,l,mi,l,*lh"))]
+ (match_operand:SI 1 "move_input_operand" "l, I,J,K,>,l,mi,l,*lh"))]
"TARGET_THUMB
&& ( register_operand (operands[0], SImode)
|| register_operand (operands[1], SImode))"
@@ -4330,7 +4340,7 @@
(const (plus:SI (pc) (const_int 4))))]
UNSPEC_PIC_BASE))
(use (label_ref (match_operand 1 "" "")))]
- "TARGET_THUMB && flag_pic"
+ "TARGET_THUMB"
"*
(*targetm.asm_out.internal_label) (asm_out_file, \"L\",
CODE_LABEL_NUMBER (operands[1]));
@@ -4345,7 +4355,7 @@
(const (plus:SI (pc) (const_int 8))))]
UNSPEC_PIC_BASE))
(use (label_ref (match_operand 1 "" "")))]
- "TARGET_ARM && flag_pic"
+ "TARGET_ARM"
"*
(*targetm.asm_out.internal_label) (asm_out_file, \"L\",
CODE_LABEL_NUMBER (operands[1]));
@@ -4354,6 +4364,74 @@
[(set_attr "predicable" "yes")]
)
+(define_insn "tls_load_dot_plus_four"
+ [(set (match_operand:SI 0 "register_operand" "+r")
+ (mem:SI (unspec:SI [(plus:SI (match_operand 1 "register_operand" "r")
+ (const (plus:SI (pc) (const_int 4))))]
+ UNSPEC_PIC_BASE)))
+ (use (label_ref (match_operand 2 "" "")))
+ (use (label_ref (match_operand 3 "" "")))]
+ "TARGET_THUMB"
+ "*
+ (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
+ CODE_LABEL_NUMBER (operands[2]));
+ return \"ldr\\t%0, [%|pc, %1]\t\t@ tls_load_dot_plus_four\";
+ "
+ [(set_attr "length" "2")]
+)
+
+(define_insn "tls_load_dot_plus_eight"
+ [(set (match_operand:SI 0 "register_operand" "+r")
+ (mem:SI (unspec:SI [(plus:SI (match_operand 1 "register_operand" "r")
+ (const (plus:SI (pc) (const_int 8))))]
+ UNSPEC_PIC_BASE)))
+ (use (label_ref (match_operand 2 "" "")))
+ (use (label_ref (match_operand 3 "" "")))]
+ "TARGET_ARM"
+ "*
+ (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
+ CODE_LABEL_NUMBER (operands[2]));
+ return \"ldr%?\\t%0, [%|pc, %1]\t\t@ tls_load_dot_plus_eight\";
+ "
+ [(set_attr "predicable" "yes")]
+)
+
+;; PIC references to local variables can generate pic_add_dot_plus_x
+;; followed by a load. These sequences can be crunched down to
+;; tls_load_dot_plus_x by a peephole.
+
+(define_peephole2
+ [(parallel [(set (match_operand:SI 0 "register_operand" "+r")
+ (unspec:SI [(plus:SI (match_dup 0)
+ (const (plus:SI (pc) (const_int 8))))]
+ UNSPEC_PIC_BASE))
+ (use (label_ref (match_operand 1 "" "")))])
+ (set (match_operand:SI 2 "register_operand" "+r") (mem:SI (match_dup 0)))]
+ "TARGET_ARM && peep2_reg_dead_p (2, operands[0])"
+ [(parallel [(set (match_operand:SI 2 "register_operand" "+r")
+ (mem:SI (unspec:SI [(plus:SI (match_dup 0)
+ (const (plus:SI (pc) (const_int 8))))]
+ UNSPEC_PIC_BASE)))
+ (use (label_ref (match_operand 1 "" "")))])]
+ ""
+)
+
+(define_peephole2
+ [(parallel [(set (match_operand:SI 0 "register_operand" "+r")
+ (unspec:SI [(plus:SI (match_dup 0)
+ (const (plus:SI (pc) (const_int 4))))]
+ UNSPEC_PIC_BASE))
+ (use (label_ref (match_operand 1 "" "")))])
+ (set (match_operand:SI 2 "register_operand" "+r") (mem:SI (match_dup 0)))]
+ "TARGET_THUMB && peep2_reg_dead_p (2, operands[0])"
+ [(parallel [(set (match_operand:SI 2 "register_operand" "+r")
+ (mem:SI (unspec:SI [(plus:SI (match_dup 0)
+ (const (plus:SI (pc) (const_int 4))))]
+ UNSPEC_PIC_BASE)))
+ (use (label_ref (match_operand 1 "" "")))])]
+ ""
+)
+
(define_expand "builtin_setjmp_receiver"
[(label_ref (match_operand 0 "" ""))]
"flag_pic"
@@ -7340,7 +7418,7 @@
if (TARGET_CALLER_INTERWORKING)
return \"bl\\t%__interwork_call_via_%0\";
else
- return \"bl\\t%__call_via_%0\";
+ return thumb_call_via_reg (operands[0]);
}"
[(set_attr "type" "call")]
)
@@ -7430,7 +7508,7 @@
if (TARGET_CALLER_INTERWORKING)
return \"bl\\t%__interwork_call_via_%1\";
else
- return \"bl\\t%__call_via_%1\";
+ return thumb_call_via_reg (operands[1]);
}"
[(set_attr "type" "call")]
)
@@ -10179,6 +10257,28 @@
}"
)
+
+;; TLS support
+
+(define_insn "load_tp_hard"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (unspec:SI [(const_int 0)] UNSPEC_TLS))]
+ "TARGET_HARD_TP"
+ "mrc%?\\tp15, 0, %0, c13, c0, 2\\t@ load_tp_hard"
+ [(set_attr "predicable" "yes")]
+)
+
+;; Doesn't clobber R1-R3
+(define_insn "load_tp_soft"
+ [(set (match_operand:SI 0 "register_operand" "=Z")
+ (unspec:SI [(const_int 0)] UNSPEC_TLS))
+ (clobber (reg:SI LR_REGNUM))
+ (clobber (reg:SI IP_REGNUM))
+ (clobber (reg:CC CC_REGNUM))]
+ "TARGET_SOFT_TP"
+ "bl\\t__aeabi_read_tp\\t@ load_tp_soft"
+)
+
;; Load the FPA co-processor patterns
(include "fpa.md")
;; Load the Maverick co-processor patterns
diff --git a/gcc/config/arm/iwmmxt.md b/gcc/config/arm/iwmmxt.md
index afdb44d0cae..9246123b66c 100644
--- a/gcc/config/arm/iwmmxt.md
+++ b/gcc/config/arm/iwmmxt.md
@@ -92,8 +92,8 @@
)
(define_insn "*iwmmxt_movsi_insn"
- [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r, m,z,r,?z,m,z")
- (match_operand:SI 1 "general_operand" "rI,K,mi,r,r,z,m,z,z"))]
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r, m,z,r,?z,Uy,z")
+ (match_operand:SI 1 "general_operand" "rI,K,mi,r,r,z,Uy,z,z"))]
"TARGET_REALLY_IWMMXT
&& ( register_operand (operands[0], SImode)
|| register_operand (operands[1], SImode))"
diff --git a/gcc/config/arm/lib1funcs.asm b/gcc/config/arm/lib1funcs.asm
index e2d5e57f118..ecd30ad0f4a 100644
--- a/gcc/config/arm/lib1funcs.asm
+++ b/gcc/config/arm/lib1funcs.asm
@@ -936,6 +936,9 @@ LSYM(Lover12):
#define ah r1
#endif
+/* Prevent __aeabi double-word shifts from being produced on SymbianOS. */
+#ifndef __symbian__
+
#ifdef L_lshrdi3
FUNC_START lshrdi3
@@ -1037,6 +1040,8 @@ LSYM(Lover12):
#endif
+#endif /* __symbian__ */
+
/* ------------------------------------------------------------------------ */
/* These next two sections are here despite the fact that they contain Thumb
assembler because their presence allows interworked code to be linked even
@@ -1169,5 +1174,4 @@ LSYM(Lchange_\register):
#include "ieee754-df.S"
#include "ieee754-sf.S"
#include "bpabi.S"
-#include "libunwind.S"
#endif /* __symbian__ */
diff --git a/gcc/config/arm/libunwind.S b/gcc/config/arm/libunwind.S
index 54051b1d26f..9838016e301 100644
--- a/gcc/config/arm/libunwind.S
+++ b/gcc/config/arm/libunwind.S
@@ -26,8 +26,8 @@
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-#ifdef L_unwind
-
+#include "lib1funcs.asm"
+
.macro UNPREFIX name
.global SYM (\name)
EQUIV SYM (\name), SYM (__\name)
@@ -108,4 +108,3 @@ ARM_FUNC_START gnu_Unwind_Save_VFP
UNWIND_WRAPPER _Unwind_RaiseException
UNWIND_WRAPPER _Unwind_Resume
-#endif /* L_unwind */
diff --git a/gcc/config/arm/linux-eabi.h b/gcc/config/arm/linux-eabi.h
index cdc98dae517..04029302c5e 100644
--- a/gcc/config/arm/linux-eabi.h
+++ b/gcc/config/arm/linux-eabi.h
@@ -36,6 +36,11 @@
#undef TARGET_DEFAULT_FLOAT_ABI
#define TARGET_DEFAULT_FLOAT_ABI ARM_FLOAT_ABI_SOFT
+/* We default to the "aapcs-linux" ABI so that enums are int-sized by
+ default. */
+#undef ARM_DEFAULT_ABI
+#define ARM_DEFAULT_ABI ARM_ABI_AAPCS_LINUX
+
#undef SUBTARGET_EXTRA_LINK_SPEC
#define SUBTARGET_EXTRA_LINK_SPEC "-m armelf_linux_eabi"
@@ -53,5 +58,7 @@
do not use -lfloat. */
#undef LIBGCC_SPEC
-/* Do not use short enums for the GNU/Linux platform. */
-#define DEFAULT_SHORT_ENUMS 0
+/* Use the AAPCS type for wchar_t, or the previous Linux default for
+ non-AAPCS. */
+#undef WCHAR_TYPE
+#define WCHAR_TYPE (TARGET_AAPCS_BASED ? "unsigned int" : "long int")
diff --git a/gcc/config/arm/linux-elf.h b/gcc/config/arm/linux-elf.h
index 3e804029533..8154e531b2a 100644
--- a/gcc/config/arm/linux-elf.h
+++ b/gcc/config/arm/linux-elf.h
@@ -1,5 +1,6 @@
/* Definitions for ARM running Linux-based GNU systems using ELF
- Copyright (C) 1993, 1994, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
+ Copyright (C) 1993, 1994, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+ 2005
Free Software Foundation, Inc.
Contributed by Philip Blundell <philb@gnu.org>
@@ -117,7 +118,8 @@
#undef ARM_FUNCTION_PROFILER
#define ARM_FUNCTION_PROFILER(STREAM, LABELNO) \
{ \
- fprintf (STREAM, "\tbl\tmcount%s\n", NEED_PLT_RELOC ? "(PLT)" : ""); \
+ fprintf (STREAM, "\tbl\tmcount%s\n", \
+ (TARGET_ARM && NEED_PLT_RELOC) ? "(PLT)" : ""); \
}
/* The linux profiler clobbers the link register. Make sure the
diff --git a/gcc/config/arm/netbsd-elf.h b/gcc/config/arm/netbsd-elf.h
index 0caf4ee1bb3..a87ec0f7b6a 100644
--- a/gcc/config/arm/netbsd-elf.h
+++ b/gcc/config/arm/netbsd-elf.h
@@ -1,5 +1,5 @@
/* Definitions of target machine for GNU compiler, NetBSD/arm ELF version.
- Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+ Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
Contributed by Wasabi Systems, Inc.
This file is part of GCC.
@@ -97,7 +97,8 @@
{ \
asm_fprintf (STREAM, "\tmov\t%Rip, %Rlr\n"); \
asm_fprintf (STREAM, "\tbl\t__mcount%s\n", \
- NEED_PLT_RELOC ? "(PLT)" : ""); \
+ (TARGET_ARM && NEED_PLT_RELOC) \
+ ? "(PLT)" : ""); \
}
/* VERY BIG NOTE: Change of structure alignment for NetBSD/arm.
diff --git a/gcc/config/arm/pr-support.c b/gcc/config/arm/pr-support.c
new file mode 100644
index 00000000000..f314fe91e04
--- /dev/null
+++ b/gcc/config/arm/pr-support.c
@@ -0,0 +1,372 @@
+/* ARM EABI compliant unwinding routines
+ Copyright (C) 2004 Free Software Foundation, Inc.
+ Contributed by Paul Brook
+
+ This file is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 2, or (at your option) any
+ later version.
+
+ In addition to the permissions in the GNU General Public License, the
+ Free Software Foundation gives you unlimited permission to link the
+ compiled version of this file into combinations with other programs,
+ and to distribute those combinations without any restriction coming
+ from the use of this file. (The General Public License restrictions
+ do apply in other respects; for example, they cover modification of
+ the file, and distribution when not linked into a combine
+ executable.)
+
+ This file is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+#include "unwind-arm.h"
+
+typedef struct _ZSt9type_info type_info; /* This names C++ type_info type */
+
+/* Misc constants. */
+#define R_IP 12
+#define R_SP 13
+#define R_LR 14
+#define R_PC 15
+
+#define uint32_highbit (((_uw) 1) << 31)
+
+void __attribute__((weak)) __cxa_call_unexpected(_Unwind_Control_Block *ucbp);
+
+/* Unwind descriptors. */
+
+typedef struct
+{
+ _uw16 length;
+ _uw16 offset;
+} EHT16;
+
+typedef struct
+{
+ _uw length;
+ _uw offset;
+} EHT32;
+
+/* Dereference a 31-bit self-relative offset.
+ Copy of routine in unwind-arm.c. */
+
+static inline _uw
+selfrel_offset31 (const _uw *p)
+{
+ _uw offset;
+
+ offset = *p;
+ /* Sign extend to 32 bits. */
+ if (offset & (1 << 30))
+ offset |= 1u << 31;
+
+ return offset + (_uw) p;
+}
+
+
+/* Personality routine helper functions. */
+
+#define CODE_FINISH (0xb0)
+
+static inline _uw8
+next_unwind_byte (__gnu_unwind_state * uws)
+{
+ _uw8 b;
+
+ if (uws->bytes_left == 0)
+ {
+ /* Load another word */
+ if (uws->words_left == 0)
+ return CODE_FINISH; /* Nothing left. */
+ uws->words_left--;
+ uws->data = *(uws->next++);
+ uws->bytes_left = 3;
+ }
+ else
+ uws->bytes_left--;
+
+ /* Extract the most significant byte. */
+ b = (uws->data >> 24) & 0xff;
+ uws->data <<= 8;
+ return b;
+}
+
+_Unwind_Reason_Code
+__gnu_unwind_execute (_Unwind_Context * context, __gnu_unwind_state * uws)
+{
+ _uw op;
+ int set_pc;
+ _uw reg;
+
+ set_pc = 0;
+ for (;;)
+ {
+ op = next_unwind_byte (uws);
+ if (op == CODE_FINISH)
+ {
+ /* If we haven't already set pc then copy it from lr. */
+ if (!set_pc)
+ {
+ _Unwind_VRS_Get (context, _UVRSC_CORE, R_LR, _UVRSD_UINT32,
+ &reg);
+ _Unwind_VRS_Set (context, _UVRSC_CORE, R_PC, _UVRSD_UINT32,
+ &reg);
+ set_pc = 1;
+ }
+ /* Drop out of the loop. */
+ break;
+ }
+ if ((op & 0x80) == 0)
+ {
+ /* vsp = vsp +- (imm6 << 2 + 4). */
+ _uw offset;
+
+ offset = ((op & 0x3f) << 2) + 4;
+ _Unwind_VRS_Get (context, _UVRSC_CORE, R_SP, _UVRSD_UINT32, &reg);
+ if (op & 0x40)
+ reg -= offset;
+ else
+ reg += offset;
+ _Unwind_VRS_Set (context, _UVRSC_CORE, R_SP, _UVRSD_UINT32, &reg);
+ continue;
+ }
+
+ if ((op & 0xf0) == 0x80)
+ {
+ op = (op << 8) | next_unwind_byte (uws);
+ if (op == 0x8000)
+ {
+ /* Refuse to unwind. */
+ return _URC_FAILURE;
+ }
+ /* Pop r4-r15 under mask. */
+ op = (op << 4) & 0xfff0;
+ if (_Unwind_VRS_Pop (context, _UVRSC_CORE, op, _UVRSD_UINT32)
+ != _UVRSR_OK)
+ return _URC_FAILURE;
+ if (op & (1 << R_PC))
+ set_pc = 1;
+ continue;
+ }
+ if ((op & 0xf0) == 0x90)
+ {
+ op &= 0xf;
+ if (op == 13 || op == 15)
+ /* Reserved. */
+ return _URC_FAILURE;
+ /* vsp = r[nnnn]. */
+ _Unwind_VRS_Get (context, _UVRSC_CORE, op, _UVRSD_UINT32, &reg);
+ _Unwind_VRS_Set (context, _UVRSC_CORE, R_SP, _UVRSD_UINT32, &reg);
+ continue;
+ }
+ if ((op & 0xf0) == 0xa0)
+ {
+ /* Pop r4-r[4+nnn], [lr]. */
+ _uw mask;
+
+ mask = (0xff0 >> (7 - (op & 7))) & 0xff0;
+ if (op & 8)
+ mask |= (1 << R_LR);
+ if (_Unwind_VRS_Pop (context, _UVRSC_CORE, mask, _UVRSD_UINT32)
+ != _UVRSR_OK)
+ return _URC_FAILURE;
+ continue;
+ }
+ if ((op & 0xf0) == 0xb0)
+ {
+ /* op == 0xb0 already handled. */
+ if (op == 0xb1)
+ {
+ op = next_unwind_byte (uws);
+ if (op == 0 || ((op & 0xf0) != 0))
+ /* Spare. */
+ return _URC_FAILURE;
+ /* Pop r0-r4 under mask. */
+ if (_Unwind_VRS_Pop (context, _UVRSC_CORE, op, _UVRSD_UINT32)
+ != _UVRSR_OK)
+ return _URC_FAILURE;
+ continue;
+ }
+ if (op == 0xb2)
+ {
+ /* vsp = vsp + 0x204 + (uleb128 << 2). */
+ int shift;
+
+ _Unwind_VRS_Get (context, _UVRSC_CORE, R_SP, _UVRSD_UINT32,
+ &reg);
+ op = next_unwind_byte (uws);
+ shift = 2;
+ while (op & 0x80)
+ {
+ reg += ((op & 0x7f) << shift);
+ shift += 7;
+ op = next_unwind_byte (uws);
+ }
+ reg += ((op & 0x7f) << shift) + 0x204;
+ _Unwind_VRS_Set (context, _UVRSC_CORE, R_SP, _UVRSD_UINT32,
+ &reg);
+ continue;
+ }
+ if (op == 0xb3)
+ {
+ /* Pop VFP registers with fldmx. */
+ op = next_unwind_byte (uws);
+ op = ((op & 0xf0) << 12) | (op & 0xf);
+ if (_Unwind_VRS_Pop (context, _UVRSC_VFP, op, _UVRSD_VFPX)
+ != _UVRSR_OK)
+ return _URC_FAILURE;
+ continue;
+ }
+ if ((op & 0xfc) == 0xb4)
+ {
+ /* Pop FPA E[4]-E[4+nn]. */
+ op = 0x40000 | ((op & 3) + 1);
+ if (_Unwind_VRS_Pop (context, _UVRSC_FPA, op, _UVRSD_FPAX)
+ != _UVRSR_OK)
+ return _URC_FAILURE;
+ continue;
+ }
+ /* op & 0xf8 == 0xb8. */
+ /* Pop VFP D[8]-D[8+nnn] with fldmx. */
+ op = 0x80000 | ((op & 7) + 1);
+ if (_Unwind_VRS_Pop (context, _UVRSC_VFP, op, _UVRSD_VFPX)
+ != _UVRSR_OK)
+ return _URC_FAILURE;
+ continue;
+ }
+ if ((op & 0xf0) == 0xc0)
+ {
+ if (op == 0xc6)
+ {
+ /* Pop iWMMXt D registers. */
+ op = next_unwind_byte (uws);
+ op = ((op & 0xf0) << 12) | (op & 0xf);
+ if (_Unwind_VRS_Pop (context, _UVRSC_WMMXD, op, _UVRSD_UINT64)
+ != _UVRSR_OK)
+ return _URC_FAILURE;
+ continue;
+ }
+ if (op == 0xc7)
+ {
+ op = next_unwind_byte (uws);
+ if (op == 0 || (op & 0xf0) != 0)
+ /* Spare. */
+ return _URC_FAILURE;
+ /* Pop iWMMXt wCGR{3,2,1,0} under mask. */
+ if (_Unwind_VRS_Pop (context, _UVRSC_WMMXC, op, _UVRSD_UINT32)
+ != _UVRSR_OK)
+ return _URC_FAILURE;
+ continue;
+ }
+ if ((op & 0xf8) == 0xc0)
+ {
+ /* Pop iWMMXt wR[10]-wR[10+nnn]. */
+ op = 0xa0000 | ((op & 0xf) + 1);
+ if (_Unwind_VRS_Pop (context, _UVRSC_WMMXD, op, _UVRSD_UINT64)
+ != _UVRSR_OK)
+ return _URC_FAILURE;
+ continue;
+ }
+ if (op == 0xc8)
+ {
+ /* Pop FPA registers. */
+ op = next_unwind_byte (uws);
+ op = ((op & 0xf0) << 12) | (op & 0xf);
+ if (_Unwind_VRS_Pop (context, _UVRSC_FPA, op, _UVRSD_FPAX)
+ != _UVRSR_OK)
+ return _URC_FAILURE;
+ continue;
+ }
+ if (op == 0xc9)
+ {
+ /* Pop VFP registers with fldmd. */
+ op = next_unwind_byte (uws);
+ op = ((op & 0xf0) << 12) | (op & 0xf);
+ if (_Unwind_VRS_Pop (context, _UVRSC_VFP, op, _UVRSD_DOUBLE)
+ != _UVRSR_OK)
+ return _URC_FAILURE;
+ continue;
+ }
+ /* Spare. */
+ return _URC_FAILURE;
+ }
+ if ((op & 0xf8) == 0xd0)
+ {
+ /* Pop VFP D[8]-D[8+nnn] with fldmd. */
+ op = 0x80000 | ((op & 7) + 1);
+ if (_Unwind_VRS_Pop (context, _UVRSC_VFP, op, _UVRSD_DOUBLE)
+ != _UVRSR_OK)
+ return _URC_FAILURE;
+ continue;
+ }
+ /* Spare. */
+ return _URC_FAILURE;
+ }
+ return _URC_OK;
+}
+
+
+/* Execute the unwinding instructions associated with a frame. */
+
+_Unwind_Reason_Code
+__gnu_unwind_frame (_Unwind_Control_Block * ucbp, _Unwind_Context * context)
+{
+ _uw *ptr;
+ __gnu_unwind_state uws;
+
+ ptr = (_uw *) ucbp->pr_cache.ehtp;
+ /* Skip over the personality routine address. */
+ ptr++;
+ /* Setup the unwinder state. */
+ uws.data = (*ptr) << 8;
+ uws.next = ptr + 1;
+ uws.bytes_left = 3;
+ uws.words_left = ((*ptr) >> 24) & 0xff;
+
+ return __gnu_unwind_execute (context, &uws);
+}
+
+/* Get the _Unwind_Control_Block from an _Unwind_Context. */
+
+static inline _Unwind_Control_Block *
+unwind_UCB_from_context (_Unwind_Context * context)
+{
+ return (_Unwind_Control_Block *) _Unwind_GetGR (context, R_IP);
+}
+
+/* Get the start address of the function being unwound. */
+
+_Unwind_Ptr
+_Unwind_GetRegionStart (_Unwind_Context * context)
+{
+ _Unwind_Control_Block *ucbp;
+
+ ucbp = unwind_UCB_from_context (context);
+ return (_Unwind_Ptr) ucbp->pr_cache.fnstart;
+}
+
+/* Find the Language specific exception data. */
+
+void *
+_Unwind_GetLanguageSpecificData (_Unwind_Context * context)
+{
+ _Unwind_Control_Block *ucbp;
+ _uw *ptr;
+
+ /* Get a pointer to the exception table entry. */
+ ucbp = unwind_UCB_from_context (context);
+ ptr = (_uw *) ucbp->pr_cache.ehtp;
+ /* Skip the personality routine address. */
+ ptr++;
+ /* Skip the unwind opcodes. */
+ ptr += (((*ptr) >> 24) & 0xff) + 1;
+
+ return ptr;
+}
+
diff --git a/gcc/config/arm/symbian.h b/gcc/config/arm/symbian.h
index 63f03c3992c..1b20f34f931 100644
--- a/gcc/config/arm/symbian.h
+++ b/gcc/config/arm/symbian.h
@@ -81,3 +81,12 @@
builtin_define ("__symbian__"); \
} \
while (false)
+
+/* On SymbianOS, these sections are not writable, so we use "a",
+ rather than "aw", for the section attributes. */
+#undef ARM_EABI_CTORS_SECTION_OP
+#define ARM_EABI_CTORS_SECTION_OP \
+ "\t.section\t.init_array,\"a\",%init_array"
+#undef ARM_EABI_DTORS_SECTION_OP
+#define ARM_EABI_DTORS_SECTION_OP \
+ "\t.section\t.fini_array,\"a\",%fini_array"
diff --git a/gcc/config/arm/t-bpabi b/gcc/config/arm/t-bpabi
index f9939e84075..fbd8fb8129e 100644
--- a/gcc/config/arm/t-bpabi
+++ b/gcc/config/arm/t-bpabi
@@ -1,11 +1,13 @@
# Add the bpabi.S functions.
-LIB1ASMFUNCS += _aeabi_lcmp _aeabi_ulcmp _aeabi_ldivmod _aeabi_uldivmod \
- _unwind
+LIB1ASMFUNCS += _aeabi_lcmp _aeabi_ulcmp _aeabi_ldivmod _aeabi_uldivmod
# Add the BPABI C functions.
LIB2FUNCS_EXTRA = $(srcdir)/config/arm/bpabi.c
-LIB2ADDEH = $(srcdir)/config/arm/unwind-arm.c $(srcdir)/unwind-c.c
+LIB2ADDEH = $(srcdir)/config/arm/unwind-arm.c \
+ $(srcdir)/config/arm/pr-support.c \
+ $(srcdir)/config/arm/libunwind.S \
+ $(srcdir)/unwind-c.c
LIB2ADDEHDEP = unwind-arm.h
# Add the BPABI names.
diff --git a/gcc/config/arm/t-symbian b/gcc/config/arm/t-symbian
index 500d6c9f762..6435e728062 100644
--- a/gcc/config/arm/t-symbian
+++ b/gcc/config/arm/t-symbian
@@ -13,7 +13,7 @@ LIB1ASMFUNCS += \
_fixsfsi _fixunssfsi
# Inlcude the gcc personality routine
-LIB2ADDEH = $(srcdir)/unwind-c.c
+LIB2ADDEH = $(srcdir)/unwind-c.c $(srcdir)/config/arm/pr-support.c
LIB2ADDEHDEP = unwind-arm.h
# Create a multilib for processors with VFP floating-point, and a
# multilib for those without -- using the soft-float ABI in both
diff --git a/gcc/config/arm/t-wrs-linux b/gcc/config/arm/t-wrs-linux
index 0022984c71a..bfa0d4cb5d5 100644
--- a/gcc/config/arm/t-wrs-linux
+++ b/gcc/config/arm/t-wrs-linux
@@ -20,6 +20,6 @@
# Boston, MA 02111-1307, USA.
# We want little-endian ARM 926 and big-endian IWMMXT libraries.
-MULTILIB_OPTIONS = tarm926ej-s/tiwmmxt
+MULTILIB_OPTIONS = tarm926ej-s/tiwmmxt/txscale
# These files must be built for each multilib.
EXTRA_MULTILIB_PARTS = crtbegin.o crtend.o crtbeginS.o crtendS.o
diff --git a/gcc/config/arm/unwind-arm.c b/gcc/config/arm/unwind-arm.c
index 14b3b84dde2..7bae7437ad5 100644
--- a/gcc/config/arm/unwind-arm.c
+++ b/gcc/config/arm/unwind-arm.c
@@ -345,7 +345,6 @@ search_EIT_table (const __EIT_entry * table, int nrec, _uw return_address)
if (nrec == 0)
return (__EIT_entry *) 0;
-
left = 0;
right = nrec - 1;
@@ -567,270 +566,6 @@ _Unwind_Complete (_Unwind_Control_Block * ucbp __attribute__((unused)))
{
}
-/* Personality routine helper functions. These should go in a separate
- file so they can be used with the arm runtime. */
-
-#define CODE_FINISH (0xb0)
-
-static inline _uw8
-next_unwind_byte (__gnu_unwind_state * uws)
-{
- _uw8 b;
-
- if (uws->bytes_left == 0)
- {
- /* Load another word */
- if (uws->words_left == 0)
- return CODE_FINISH; /* Nothing left. */
- uws->words_left--;
- uws->data = *(uws->next++);
- uws->bytes_left = 3;
- }
- else
- uws->bytes_left--;
-
- /* Extract the most significant byte. */
- b = (uws->data >> 24) & 0xff;
- uws->data <<= 8;
- return b;
-}
-
-static _Unwind_Reason_Code
-__gnu_unwind_execute (_Unwind_Context * context, __gnu_unwind_state * uws)
-{
- _uw op;
- int set_pc;
- _uw reg;
-
- set_pc = 0;
- for (;;)
- {
- op = next_unwind_byte (uws);
- if (op == CODE_FINISH)
- {
- /* If we haven't already set pc then copy it from lr. */
- if (!set_pc)
- {
- _Unwind_VRS_Get (context, _UVRSC_CORE, R_LR, _UVRSD_UINT32,
- &reg);
- _Unwind_VRS_Set (context, _UVRSC_CORE, R_PC, _UVRSD_UINT32,
- &reg);
- set_pc = 1;
- }
- /* Drop out of the loop. */
- break;
- }
- if ((op & 0x80) == 0)
- {
- /* vsp = vsp +- (imm6 << 2 + 4). */
- _uw offset;
-
- offset = ((op & 0x3f) << 2) + 4;
- _Unwind_VRS_Get (context, _UVRSC_CORE, R_SP, _UVRSD_UINT32, &reg);
- if (op & 0x40)
- reg -= offset;
- else
- reg += offset;
- _Unwind_VRS_Set (context, _UVRSC_CORE, R_SP, _UVRSD_UINT32, &reg);
- continue;
- }
-
- if ((op & 0xf0) == 0x80)
- {
- op = (op << 8) | next_unwind_byte (uws);
- if (op == 0x8000)
- {
- /* Refuse to unwind. */
- return _URC_FAILURE;
- }
- /* Pop r4-r15 under mask. */
- op = (op << 4) & 0xfff0;
- if (_Unwind_VRS_Pop (context, _UVRSC_CORE, op, _UVRSD_UINT32)
- != _UVRSR_OK)
- return _URC_FAILURE;
- if (op & (1 << R_PC))
- set_pc = 1;
- continue;
- }
- if ((op & 0xf0) == 0x90)
- {
- op &= 0xf;
- if (op == 13 || op == 15)
- /* Reserved. */
- return _URC_FAILURE;
- /* vsp = r[nnnn]. */
- _Unwind_VRS_Get (context, _UVRSC_CORE, op, _UVRSD_UINT32, &reg);
- _Unwind_VRS_Set (context, _UVRSC_CORE, R_SP, _UVRSD_UINT32, &reg);
- continue;
- }
- if ((op & 0xf0) == 0xa0)
- {
- /* Pop r4-r[4+nnn], [lr]. */
- _uw mask;
-
- mask = (0xff0 >> (7 - (op & 7))) & 0xff0;
- if (op & 8)
- mask |= (1 << R_LR);
- if (_Unwind_VRS_Pop (context, _UVRSC_CORE, mask, _UVRSD_UINT32)
- != _UVRSR_OK)
- return _URC_FAILURE;
- continue;
- }
- if ((op & 0xf0) == 0xb0)
- {
- /* op == 0xb0 already handled. */
- if (op == 0xb1)
- {
- op = next_unwind_byte (uws);
- if (op == 0 || ((op & 0xf0) != 0))
- /* Spare. */
- return _URC_FAILURE;
- /* Pop r0-r4 under mask. */
- if (_Unwind_VRS_Pop (context, _UVRSC_CORE, op, _UVRSD_UINT32)
- != _UVRSR_OK)
- return _URC_FAILURE;
- continue;
- }
- if (op == 0xb2)
- {
- /* vsp = vsp + 0x204 + (uleb128 << 2). */
- int shift;
-
- _Unwind_VRS_Get (context, _UVRSC_CORE, R_SP, _UVRSD_UINT32,
- &reg);
- op = next_unwind_byte (uws);
- shift = 2;
- while (op & 0x80)
- {
- reg += ((op & 0x7f) << shift);
- shift += 7;
- op = next_unwind_byte (uws);
- }
- reg += ((op & 0x7f) << shift) + 0x204;
- _Unwind_VRS_Set (context, _UVRSC_CORE, R_SP, _UVRSD_UINT32,
- &reg);
- continue;
- }
- if (op == 0xb3)
- {
- /* Pop VFP registers with fldmx. */
- op = next_unwind_byte (uws);
- op = ((op & 0xf0) << 12) | (op & 0xf);
- if (_Unwind_VRS_Pop (context, _UVRSC_VFP, op, _UVRSD_VFPX)
- != _UVRSR_OK)
- return _URC_FAILURE;
- continue;
- }
- if ((op & 0xfc) == 0xb4)
- {
- /* Pop FPA E[4]-E[4+nn]. */
- op = 0x40000 | ((op & 3) + 1);
- if (_Unwind_VRS_Pop (context, _UVRSC_FPA, op, _UVRSD_FPAX)
- != _UVRSR_OK)
- return _URC_FAILURE;
- continue;
- }
- /* op & 0xf8 == 0xb8. */
- /* Pop VFP D[8]-D[8+nnn] with fldmx. */
- op = 0x80000 | ((op & 7) + 1);
- if (_Unwind_VRS_Pop (context, _UVRSC_VFP, op, _UVRSD_VFPX)
- != _UVRSR_OK)
- return _URC_FAILURE;
- continue;
- }
- if ((op & 0xf0) == 0xc0)
- {
- if (op == 0xc6)
- {
- /* Pop iWMMXt D registers. */
- op = next_unwind_byte (uws);
- op = ((op & 0xf0) << 12) | (op & 0xf);
- if (_Unwind_VRS_Pop (context, _UVRSC_WMMXD, op, _UVRSD_UINT64)
- != _UVRSR_OK)
- return _URC_FAILURE;
- continue;
- }
- if (op == 0xc7)
- {
- op = next_unwind_byte (uws);
- if (op == 0 || (op & 0xf0) != 0)
- /* Spare. */
- return _URC_FAILURE;
- /* Pop iWMMXt wCGR{3,2,1,0} under mask. */
- if (_Unwind_VRS_Pop (context, _UVRSC_WMMXC, op, _UVRSD_UINT32)
- != _UVRSR_OK)
- return _URC_FAILURE;
- continue;
- }
- if ((op & 0xf8) == 0xc0)
- {
- /* Pop iWMMXt wR[10]-wR[10+nnn]. */
- op = 0xa0000 | ((op & 0xf) + 1);
- if (_Unwind_VRS_Pop (context, _UVRSC_WMMXD, op, _UVRSD_UINT64)
- != _UVRSR_OK)
- return _URC_FAILURE;
- continue;
- }
- if (op == 0xc8)
- {
- /* Pop FPA registers. */
- op = next_unwind_byte (uws);
- op = ((op & 0xf0) << 12) | (op & 0xf);
- if (_Unwind_VRS_Pop (context, _UVRSC_FPA, op, _UVRSD_FPAX)
- != _UVRSR_OK)
- return _URC_FAILURE;
- continue;
- }
- if (op == 0xc9)
- {
- /* Pop VFP registers with fldmd. */
- op = next_unwind_byte (uws);
- op = ((op & 0xf0) << 12) | (op & 0xf);
- if (_Unwind_VRS_Pop (context, _UVRSC_VFP, op, _UVRSD_DOUBLE)
- != _UVRSR_OK)
- return _URC_FAILURE;
- continue;
- }
- /* Spare. */
- return _URC_FAILURE;
- }
- if ((op & 0xf8) == 0xd0)
- {
- /* Pop VFP D[8]-D[8+nnn] with fldmd. */
- op = 0x80000 | ((op & 7) + 1);
- if (_Unwind_VRS_Pop (context, _UVRSC_VFP, op, _UVRSD_DOUBLE)
- != _UVRSR_OK)
- return _URC_FAILURE;
- continue;
- }
- /* Spare. */
- return _URC_FAILURE;
- }
- return _URC_OK;
-}
-
-
-/* Execute the unwinding instructions associated with a frame. */
-
-_Unwind_Reason_Code
-__gnu_unwind_frame (_Unwind_Control_Block * ucbp, _Unwind_Context * context)
-{
- _uw *ptr;
- __gnu_unwind_state uws;
-
- ptr = (_uw *) ucbp->pr_cache.ehtp;
- /* Skip over the personality routine address. */
- ptr++;
- /* Setup the unwinder state. */
- uws.data = (*ptr) << 8;
- uws.next = ptr + 1;
- uws.bytes_left = 3;
- uws.words_left = ((*ptr) >> 24) & 0xff;
-
- return __gnu_unwind_execute (context, &uws);
-}
-
-
/* Get the _Unwind_Control_Block from an _Unwind_Context. */
static inline _Unwind_Control_Block *
@@ -840,38 +575,6 @@ unwind_UCB_from_context (_Unwind_Context * context)
}
-/* Find the Language specific exception data. */
-
-void *
-_Unwind_GetLanguageSpecificData (_Unwind_Context * context)
-{
- _Unwind_Control_Block *ucbp;
- _uw *ptr;
-
- /* Get a pointer to the exception table entry. */
- ucbp = unwind_UCB_from_context (context);
- ptr = (_uw *) ucbp->pr_cache.ehtp;
- /* Skip the prersonality routine address. */
- ptr++;
- /* Skip the unwind opcodes. */
- ptr += (((*ptr) >> 24) & 0xff) + 1;
-
- return ptr;
-}
-
-
-/* Get the start address of the function being unwound. */
-
-_Unwind_Ptr
-_Unwind_GetRegionStart (_Unwind_Context * context)
-{
- _Unwind_Control_Block *ucbp;
-
- ucbp = unwind_UCB_from_context (context);
- return (_Unwind_Ptr) ucbp->pr_cache.fnstart;
-}
-
-
/* Free an exception. */
void
diff --git a/gcc/config/arm/wrs-linux.h b/gcc/config/arm/wrs-linux.h
index ae0c2507c9c..13a40f408e8 100644
--- a/gcc/config/arm/wrs-linux.h
+++ b/gcc/config/arm/wrs-linux.h
@@ -28,7 +28,8 @@ Boston, MA 02111-1307, USA. */
#undef CC1_SPEC
#define CC1_SPEC " \
%{tarm926ej-s: -mcpu=arm926ej-s ; \
- tiwmmxt: -mcpu=iwmmxt -mbig-endian } \
+ tiwmmxt: -mcpu=iwmmxt -mbig-endian ; \
+ txscale: -mcpu=xscale -mbig-endian } \
%{profile:-p}"
/* Since the ARM926EJ-S is the default processor, we do not need to
@@ -40,16 +41,19 @@ Boston, MA 02111-1307, USA. */
/* Translate -tiwmmxt appropriately for the assembler. The -meabi=4
option is SUBTARGET_EXTRA_ASM_SPEC in bpabi.h. */
#undef SUBTARGET_EXTRA_ASM_SPEC
-#define SUBTARGET_EXTRA_ASM_SPEC "%{tiwmmxt:-mcpu=iwmmxt -EB} -meabi=4"
+#define SUBTARGET_EXTRA_ASM_SPEC \
+ "%{tiwmmxt:-mcpu=iwmmxt -EB} %{txscale:-mcpu=xscale -EB} -meabi=4"
/* Translate -tiwmmxt for the linker. */
#undef SUBTARGET_EXTRA_LINK_SPEC
-#define SUBTARGET_EXTRA_LINK_SPEC \
- "%{tiwmmxt:-m armelfb_linux_eabi ; : -m armelf_linux_eabi}"
+#define SUBTARGET_EXTRA_LINK_SPEC \
+ "%{tiwmmxt:-m armelfb_linux_eabi ; \
+ txscale:-m armelfb_linux_eabi ; \
+ : -m armelf_linux_eabi}"
/* When using -tiwmmxt, search the "tiwmmxt" subdirectory. */
#undef SYSROOT_SUFFIX_SPEC
#define SYSROOT_SUFFIX_SPEC \
- "/%{tiwmmxt:/tiwmmxt}"
+ "/%{tiwmmxt:/tiwmmxt}%{txscale:/txscale}"
diff --git a/gcc/config/elfos.h b/gcc/config/elfos.h
index 6a138f9f76f..b726313188f 100644
--- a/gcc/config/elfos.h
+++ b/gcc/config/elfos.h
@@ -216,7 +216,15 @@ Boston, MA 02111-1307, USA. */
fprintf ((FILE), "%s\n", ASM_SECTION_START_OP)
#endif
-#define MAKE_DECL_ONE_ONLY(DECL) (DECL_WEAK (DECL) = 1)
+/* Don't use weak for entities with vague linkage when HAVE_GAS_COMDAT_GROUP
+ is true. */
+#define MAKE_DECL_ONE_ONLY(DECL) \
+ do \
+ { \
+ if (!HAVE_GAS_COMDAT_GROUP) \
+ DECL_WEAK(DECL) = 1; \
+ } \
+ while (0)
/* Switch into a generic section. */
#define TARGET_ASM_NAMED_SECTION default_elf_asm_named_section
diff --git a/gcc/config/ia64/ia64.h b/gcc/config/ia64/ia64.h
index 5aab0a34810..6f3ab458fbb 100644
--- a/gcc/config/ia64/ia64.h
+++ b/gcc/config/ia64/ia64.h
@@ -2338,6 +2338,8 @@ extern int ia64_final_schedule;
#define TARGET_UNWIND_INFO 1
+#define TARGET_UNWIND_TABLES_DEFAULT true
+
#define EH_RETURN_DATA_REGNO(N) ((N) < 4 ? (N) + 15 : INVALID_REGNUM)
/* This function contains machine specific function data. */
diff --git a/gcc/configure b/gcc/configure
index 11cf128f204..cb8258fe770 100755
--- a/gcc/configure
+++ b/gcc/configure
@@ -9871,10 +9871,12 @@ then
BUILD_PREFIX_1=build-
BUILD_CFLAGS='$(INTERNAL_CFLAGS) $(T_CFLAGS) $(CFLAGS_FOR_BUILD)'
- if test "x$TARGET_SYSTEM_ROOT" = x; then
- STMP_FIXINC=
- STMP_FIXPROTO=
- fi
+ # These programs are not set up to work in a Canadian cross
+ # environment. In particular, fixincludes runs on the build machine,
+ # but fixlib.h includes system.h, which describes properties of
+ # the host machine.
+ STMP_FIXINC=
+ STMP_FIXPROTO=
fi
# Expand extra_headers to include complete path.
@@ -10801,6 +10803,19 @@ foo: .long 25
tls_first_minor=13
tls_as_opt=--fatal-warnings
;;
+ arm*-*-*)
+ conftest_s='
+ .section ".tdata","awT",%progbits
+foo: .long 25
+ .text
+.word foo(gottpoff)
+.word foo(tpoff)
+.word foo(tlsgd)
+.word foo(tlsldm)
+.word foo(tlsldo)'
+ tls_first_major=2
+ tls_first_minor=17
+ ;;
i[34567]86-*-*)
conftest_s='
.section ".tdata","awT",@progbits
diff --git a/gcc/configure.ac b/gcc/configure.ac
index 80b5e12977c..8de38197d03 100644
--- a/gcc/configure.ac
+++ b/gcc/configure.ac
@@ -1,7 +1,7 @@
# configure.ac for GCC
# Process this file with autoconf to generate a configuration script.
-# Copyright 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
+# Copyright 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
# Free Software Foundation, Inc.
#This file is part of GCC.
@@ -1534,10 +1534,12 @@ then
BUILD_PREFIX_1=build-
BUILD_CFLAGS='$(INTERNAL_CFLAGS) $(T_CFLAGS) $(CFLAGS_FOR_BUILD)'
- if test "x$TARGET_SYSTEM_ROOT" = x; then
- STMP_FIXINC=
- STMP_FIXPROTO=
- fi
+ # These programs are not set up to work in a Canadian cross
+ # environment. In particular, fixincludes runs on the build machine,
+ # but fixlib.h includes system.h, which describes properties of
+ # the host machine.
+ STMP_FIXINC=
+ STMP_FIXPROTO=
fi
# Expand extra_headers to include complete path.
@@ -2100,6 +2102,19 @@ foo: .long 25
tls_first_minor=13
tls_as_opt=--fatal-warnings
;;
+ arm*-*-*)
+ conftest_s='
+ .section ".tdata","awT",%progbits
+foo: .long 25
+ .text
+.word foo(gottpoff)
+.word foo(tpoff)
+.word foo(tlsgd)
+.word foo(tlsldm)
+.word foo(tlsldo)'
+ tls_first_major=2
+ tls_first_minor=17
+ ;;
i[34567]86-*-*)
conftest_s='
.section ".tdata","awT",@progbits
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 35fdb5b768d..81a334f1d43 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -6477,7 +6477,7 @@ architectures:
@item -mabi=@var{name}
@opindex mabi
Generate code for the specified ABI. Permissible values are: @samp{apcs-gnu},
-@samp{atpcs}, @samp{aapcs} and @samp{iwmmxt}.
+@samp{atpcs}, @samp{aapcs}, @samp{aapcs-linux} and @samp{iwmmxt}.
@item -mapcs-frame
@opindex mapcs-frame
diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index 613ca269bbe..16bb75ec8e4 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -7684,7 +7684,10 @@ Given a register, this hook should return a parallel of registers to
represent where to find the register pieces. Define this hook if the
register and its mode are represented in Dwarf in non-contiguous
locations, or if the register should be represented in more than one
-register in Dwarf. Otherwise, this hook should return @code{NULL_RTX}.
+register in Dwarf. This hook can also return @code{reg} to force the
+register to be referenced as a single register, even if gcc thinks it is
+split over multiple consecutive registers. Otherwise, this hook should
+return @code{NULL_RTX}.
If not defined, the default is to return @code{NULL_RTX}.
@end deftypefn
diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index 3eed33c6f2d..eaa963ddac2 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -8127,6 +8127,16 @@ multiple_reg_loc_descriptor (rtx rtl, rtx regs)
return loc_result;
}
+ /* A single register. This happens when a single dwarf register overlaps
+ multiple gcc registers. */
+
+ if (GET_CODE (regs) == REG)
+ {
+ reg = dbx_reg_number (regs);
+
+ return one_reg_loc_descriptor (reg);
+ }
+
/* Now onto stupid register sets in non contiguous locations. */
if (GET_CODE (regs) != PARALLEL)
diff --git a/gcc/expr.h b/gcc/expr.h
index dd7ac9c6058..900f8642fd8 100644
--- a/gcc/expr.h
+++ b/gcc/expr.h
@@ -585,6 +585,8 @@ extern rtx hard_function_value (tree, tree, int);
extern rtx prepare_call_address (rtx, tree, rtx *, int, int);
+extern bool shift_return_value (enum machine_mode mode, bool, rtx);
+
extern rtx expand_call (tree, rtx, int);
#ifdef TREE_CODE
diff --git a/gcc/function.c b/gcc/function.c
index 1a1cd78b778..485cd8be723 100644
--- a/gcc/function.c
+++ b/gcc/function.c
@@ -6725,22 +6725,33 @@ expand_function_start (tree subr, int parms_have_cleanups)
{
/* Compute the return values into a pseudo reg, which we will copy
into the true return register after the cleanups are done. */
-
- /* In order to figure out what mode to use for the pseudo, we
- figure out what the mode of the eventual return register will
- actually be, and use that. */
- rtx hard_reg
- = hard_function_value (TREE_TYPE (DECL_RESULT (subr)),
- subr, 1);
-
- /* Structures that are returned in registers are not aggregate_value_p,
- so we may see a PARALLEL or a REG. */
- if (REG_P (hard_reg))
- SET_DECL_RTL (DECL_RESULT (subr), gen_reg_rtx (GET_MODE (hard_reg)));
- else if (GET_CODE (hard_reg) == PARALLEL)
- SET_DECL_RTL (DECL_RESULT (subr), gen_group_rtx (hard_reg));
+ tree return_type = TREE_TYPE (DECL_RESULT (subr));
+ if (TYPE_MODE (return_type) != BLKmode
+ && targetm.calls.return_in_msb (return_type))
+ /* expand_function_end will insert the appropriate padding in
+ this case. Use the return value's natural (unpadded) mode
+ within the function proper. */
+ SET_DECL_RTL (DECL_RESULT (subr),
+ gen_reg_rtx (TYPE_MODE (return_type)));
else
- abort ();
+ {
+ /* In order to figure out what mode to use for the pseudo, we
+ figure out what the mode of the eventual return register will
+ actually be, and use that. */
+ rtx hard_reg = hard_function_value (return_type, subr, 1);
+
+ /* Structures that are returned in registers are not
+ aggregate_value_p, so we may see a PARALLEL or a REG. */
+ if (REG_P (hard_reg))
+ SET_DECL_RTL (DECL_RESULT (subr),
+ gen_reg_rtx (GET_MODE (hard_reg)));
+ else
+ {
+ if (GET_CODE (hard_reg) != PARALLEL)
+ abort ();
+ SET_DECL_RTL (DECL_RESULT (subr), gen_group_rtx (hard_reg));
+ }
+ }
/* Set DECL_REGISTER flag so that expand_function_end will copy the
result to the real return register(s). */
@@ -7152,10 +7163,22 @@ expand_function_end (void)
if (GET_MODE (real_decl_rtl) == BLKmode)
PUT_MODE (real_decl_rtl, GET_MODE (decl_rtl));
+ /* If a non-BLKmode return value should be padded at the least
+ significant end of the register, shift it left by the appropriate
+ amount. Blkmode results are handled using the group load/store
+ machinery. */
+ if (TYPE_MODE (TREE_TYPE (decl_result)) != BLKmode
+ && targetm.calls.return_in_msb (TREE_TYPE (decl_result)))
+ {
+ emit_move_insn (gen_rtx_REG (GET_MODE (decl_rtl),
+ REGNO (real_decl_rtl)),
+ decl_rtl);
+ shift_return_value (GET_MODE (decl_rtl), true, real_decl_rtl);
+ }
/* If a named return value dumped decl_return to memory, then
we may need to re-do the PROMOTE_MODE signed/unsigned
extension. */
- if (GET_MODE (real_decl_rtl) != GET_MODE (decl_rtl))
+ else if (GET_MODE (real_decl_rtl) != GET_MODE (decl_rtl))
{
int unsignedp = TREE_UNSIGNED (TREE_TYPE (decl_result));
diff --git a/gcc/haifa-sched.c b/gcc/haifa-sched.c
index 2710132ec3e..1bf06c76ce6 100644
--- a/gcc/haifa-sched.c
+++ b/gcc/haifa-sched.c
@@ -1,6 +1,6 @@
/* Instruction scheduling pass.
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+ 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
Contributed by Michael Tiemann (tiemann@cygnus.com) Enhanced by,
and currently maintained by, Jim Wilson (wilson@cygnus.com)
@@ -2563,8 +2563,8 @@ schedule_block (int b, int rgn_n_insns)
insn, can_issue_more);
/* A naked CLOBBER or USE generates no instruction, so do
not count them against the issue rate. */
- else if (GET_CODE (PATTERN (insn)) != USE
- && GET_CODE (PATTERN (insn)) != CLOBBER)
+ else if (INSN_P (insn) && (GET_CODE (PATTERN (insn)) != USE
+ && GET_CODE (PATTERN (insn)) != CLOBBER))
can_issue_more--;
advance = schedule_insn (insn, &ready, clock_var);
diff --git a/gcc/jump.c b/gcc/jump.c
index ce803a9e1e0..8e0642695fc 100644
--- a/gcc/jump.c
+++ b/gcc/jump.c
@@ -1,6 +1,6 @@
/* Optimize jump instructions, for GNU compiler.
Copyright (C) 1987, 1988, 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1997
- 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+ 1998, 1999, 2000, 2001, 2002, 2003, 2005 Free Software Foundation, Inc.
This file is part of GCC.
@@ -55,6 +55,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "reload.h"
#include "predict.h"
#include "timevar.h"
+#include "target.h"
/* Optimize jump y; x: ... y: jumpif... x?
Don't know if it is worth bothering with. */
@@ -335,6 +336,7 @@ duplicate_loop_exit_test (rtx loop_start)
is a CODE_LABEL
has a REG_RETVAL or REG_LIBCALL note (hard to adjust)
is a NOTE_INSN_LOOP_BEG because this means we have a nested loop
+ is not copyable
We also do not do this if we find an insn with ASM_OPERANDS. While
this restriction should not be necessary, copying an insn with
@@ -348,6 +350,10 @@ duplicate_loop_exit_test (rtx loop_start)
&& NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_END);
insn = NEXT_INSN (insn))
{
+ if (targetm.cannot_copy_insn_p
+ && (*targetm.cannot_copy_insn_p) (insn))
+ return 0;
+
switch (GET_CODE (insn))
{
case CODE_LABEL:
diff --git a/gcc/optabs.c b/gcc/optabs.c
index a9fd01dcf21..180a828b779 100644
--- a/gcc/optabs.c
+++ b/gcc/optabs.c
@@ -1869,6 +1869,40 @@ expand_binop (enum machine_mode mode, optab binoptab, rtx op0, rtx op1,
return 0;
}
+
+/* Like expand_binop, but return a constant rtx if the result can be
+ * calculated at compile time. The arguments and return value are
+ * otherwise the same as for expand_binop. */
+
+static rtx
+simplify_expand_binop (enum machine_mode mode, optab binoptab,
+ rtx op0, rtx op1, rtx target, int unsignedp,
+ enum optab_methods methods)
+{
+ if (CONSTANT_P (op0) && CONSTANT_P (op1))
+ return simplify_gen_binary (binoptab->code, mode, op0, op1);
+ else
+ return expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods);
+}
+
+/* Like simplify_expand_binop, but always put the result in TARGET.
+ * Return true if the expansion succeeded. */
+
+bool
+force_expand_binop (enum machine_mode mode, optab binoptab,
+ rtx op0, rtx op1, rtx target, int unsignedp,
+ enum optab_methods methods)
+{
+ rtx x = simplify_expand_binop (mode, binoptab, op0, op1,
+ target, unsignedp, methods);
+ if (x == 0)
+ return false;
+ if (x != target)
+ emit_move_insn (target, x);
+ return true;
+}
+
+
/* Like expand_binop, but for open-coding vectors binops. */
static rtx
@@ -2301,6 +2335,9 @@ expand_twoval_binop_libfunc (optab binoptab, rtx op0, rtx op1,
if (!((targ0 != NULL_RTX) ^ (targ1 != NULL_RTX)))
abort ();
+ op0 = protect_from_queue (op0, 0);
+ op1 = protect_from_queue (op1, 0);
+
mode = GET_MODE (op0);
if (!binoptab->handlers[(int) mode].libfunc)
return false;
diff --git a/gcc/optabs.h b/gcc/optabs.h
index 65c6ac5ddba..565e39f491d 100644
--- a/gcc/optabs.h
+++ b/gcc/optabs.h
@@ -370,6 +370,9 @@ extern enum insn_code cmpmem_optab[NUM_MACHINE_MODES];
extern rtx expand_binop (enum machine_mode, optab, rtx, rtx, rtx, int,
enum optab_methods);
+extern bool force_expand_binop (enum machine_mode, optab, rtx, rtx, rtx, int,
+ enum optab_methods);
+
/* Expand a binary operation with both signed and unsigned forms. */
extern rtx sign_expand_binop (enum machine_mode, optab, optab, rtx, rtx,
rtx, int, enum optab_methods);
diff --git a/gcc/opts.c b/gcc/opts.c
index 09684345bd5..a9a51051a54 100644
--- a/gcc/opts.c
+++ b/gcc/opts.c
@@ -37,6 +37,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "diagnostic.h"
#include "tm_p.h" /* For OPTIMIZATION_OPTIONS. */
#include "insn-attr.h" /* For INSN_SCHEDULING. */
+#include "target.h"
/* Value of the -G xx switch, and whether it was passed or not. */
unsigned HOST_WIDE_INT g_switch_value;
@@ -609,11 +610,8 @@ decode_options (unsigned int argc, const char **argv)
target_flags = 0;
set_target_switch ("");
- /* Unwind tables are always present when a target has ABI-specified unwind
- tables, so the default should be ON. */
-#ifdef TARGET_UNWIND_INFO
- flag_unwind_tables = TARGET_UNWIND_INFO;
-#endif
+ /* Some tagets have ABI-specified unwind tables. */
+ flag_unwind_tables = targetm.unwind_tables_default;
#ifdef OPTIMIZATION_OPTIONS
/* Allow default optimizations to be specified on a per-machine basis. */
diff --git a/gcc/postreload.c b/gcc/postreload.c
index da740cfaa8b..4832937189c 100644
--- a/gcc/postreload.c
+++ b/gcc/postreload.c
@@ -1,6 +1,6 @@
/* Perform simple optimizations to clean up the result of reload.
Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+ 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
This file is part of GCC.
@@ -410,6 +410,8 @@ reload_cse_simplify_operands (rtx insn, rtx testreg)
right, so avoid the problem here. Likewise if we have a constant
and the insn pattern doesn't tell us the mode we need. */
if (GET_CODE (recog_data.operand[i]) == CODE_LABEL
+ || (GET_CODE (recog_data.operand[i]) == NOTE
+ && NOTE_LINE_NUMBER (recog_data.operand[i]) == NOTE_INSN_DELETED_LABEL)
|| (CONSTANT_P (recog_data.operand[i])
&& recog_data.operand_mode[i] == VOIDmode))
continue;
diff --git a/gcc/stmt.c b/gcc/stmt.c
index 38271751099..9bced0821e1 100644
--- a/gcc/stmt.c
+++ b/gcc/stmt.c
@@ -405,7 +405,6 @@ static bool check_unique_operand_names (tree, tree);
static char *resolve_operand_name_1 (char *, tree, tree);
static void expand_null_return_1 (rtx);
static enum br_predictor return_prediction (rtx);
-static rtx shift_return_value (rtx);
static void expand_value_return (rtx);
static int tail_recursion_args (tree, tree);
static void expand_cleanups (tree, int, int);
@@ -2947,33 +2946,6 @@ return_prediction (rtx val)
}
-/* If the current function returns values in the most significant part
- of a register, shift return value VAL appropriately. The mode of
- the function's return type is known not to be BLKmode. */
-
-static rtx
-shift_return_value (rtx val)
-{
- tree type;
-
- type = TREE_TYPE (DECL_RESULT (current_function_decl));
- if (targetm.calls.return_in_msb (type))
- {
- rtx target;
- HOST_WIDE_INT shift;
-
- target = DECL_RTL (DECL_RESULT (current_function_decl));
- shift = (GET_MODE_BITSIZE (GET_MODE (target))
- - BITS_PER_UNIT * int_size_in_bytes (type));
- if (shift > 0)
- val = expand_binop (GET_MODE (target), ashl_optab,
- gen_lowpart (GET_MODE (target), val),
- GEN_INT (shift), target, 1, OPTAB_WIDEN);
- }
- return val;
-}
-
-
/* Generate RTL to return from the current function, with value VAL. */
static void
@@ -3258,8 +3230,9 @@ expand_return (tree retval)
val = expand_expr (retval_rhs, val, GET_MODE (val), 0);
val = force_not_mem (val);
emit_queue ();
+
/* Return the calculated value, doing cleanups first. */
- expand_value_return (shift_return_value (val));
+ expand_value_return (val);
}
else
{
@@ -3267,6 +3240,7 @@ expand_return (tree retval)
calculate value into hard return reg. */
expand_expr (retval, const0_rtx, VOIDmode, 0);
emit_queue ();
+
expand_value_return (result_rtl);
}
}
diff --git a/gcc/target-def.h b/gcc/target-def.h
index b61ca206701..e8c1487e690 100644
--- a/gcc/target-def.h
+++ b/gcc/target-def.h
@@ -368,6 +368,9 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
TARGET_SPLIT_COMPLEX_ARG, \
}
+#ifndef TARGET_UNWIND_TABLES_DEFAULT
+#define TARGET_UNWIND_TABLES_DEFAULT false
+#endif
/* C++ specific. */
#ifndef TARGET_CXX_GUARD_TYPE
@@ -470,6 +473,7 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
TARGET_TERMINATE_DW2_EH_FRAME_INFO, \
TARGET_ASM_FILE_START_APP_OFF, \
TARGET_ASM_FILE_START_FILE_DIRECTIVE, \
+ TARGET_UNWIND_TABLES_DEFAULT, \
}
#include "hooks.h"
diff --git a/gcc/target.h b/gcc/target.h
index f24f9304bc6..298e3680c12 100644
--- a/gcc/target.h
+++ b/gcc/target.h
@@ -510,6 +510,9 @@ struct gcc_target
at the beginning of assembly output. */
bool file_start_file_directive;
+ /* True if unwinding tables should be generated by default. */
+ bool unwind_tables_default;
+
/* Leave the boolean fields at the end. */
};
diff --git a/gcc/testsuite/gcc.dg/divmod-1.c b/gcc/testsuite/gcc.dg/divmod-1.c
new file mode 100644
index 00000000000..a2c1564b7fa
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/divmod-1.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+/* expand_twoval_binop_libfunc wasn't calling protect_from_queue. */
+int b;
+int
+foo (int a)
+{
+ return a % (b--);
+}
diff --git a/gcc/testsuite/gcc.dg/pack-test-4.c b/gcc/testsuite/gcc.dg/pack-test-4.c
index 27ae0cdcc77..76569d1a2a8 100644
--- a/gcc/testsuite/gcc.dg/pack-test-4.c
+++ b/gcc/testsuite/gcc.dg/pack-test-4.c
@@ -29,4 +29,5 @@ int main (void)
if (b->flag1 != 0)
abort ();
+ return 0;
}
diff --git a/gcc/testsuite/gcc.misc-tests/bprob.exp b/gcc/testsuite/gcc.misc-tests/bprob.exp
index 8fde6829f83..a74c76bde1a 100644
--- a/gcc/testsuite/gcc.misc-tests/bprob.exp
+++ b/gcc/testsuite/gcc.misc-tests/bprob.exp
@@ -21,7 +21,7 @@ load_lib target-supports.exp
# Some targets don't have any implementation of __bb_init_func or are
# missing other needed machinery.
-if { ![check_profiling_available "-fprofile-arcs"] } {
+if { ![check_profiling_available "-fprofile-arcs"] } {
return
}
diff --git a/gcc/testsuite/lib/g++.exp b/gcc/testsuite/lib/g++.exp
index d7ab8bbb539..eafe1b8317e 100644
--- a/gcc/testsuite/lib/g++.exp
+++ b/gcc/testsuite/lib/g++.exp
@@ -128,20 +128,22 @@ proc g++_link_flags { paths } {
if [file exists "${gccpath}/librx/librx.a"] {
append flags "-L${gccpath}/librx "
}
- append ld_library_path ":${rootme}"
- set compiler [lindex $GXX_UNDER_TEST 0]
- if { [is_remote host] == 0 && [which $compiler] != 0 } {
- foreach i "[exec $compiler --print-multi-lib]" {
- set mldir ""
- regexp -- "\[a-z0-9=/\.-\]*;" $i mldir
- set mldir [string trimright $mldir "\;@"]
- if { "$mldir" == "." } {
- continue
+ if {[info exists rootme]} {
+ append ld_library_path ":${rootme}"
+ set compiler [lindex $GXX_UNDER_TEST 0]
+ if { [is_remote host] == 0 && [which $compiler] != 0 } {
+ foreach i "[exec $compiler --print-multi-lib]" {
+ set mldir ""
+ regexp -- "\[a-z0-9=/\.-\]*;" $i mldir
+ set mldir [string trimright $mldir "\;@"]
+ if { "$mldir" == "." } {
+ continue
+ }
+ if { [llength [glob -nocomplain ${rootme}/${mldir}/libgcc_s*.so.*]] >= 1 } {
+ append ld_library_path ":${rootme}/${mldir}"
+ }
+ }
}
- if { [llength [glob -nocomplain ${rootme}/${mldir}/libgcc_s*.so.*]] >= 1 } {
- append ld_library_path ":${rootme}/${mldir}"
- }
- }
}
} else {
global tool_root_dir;
@@ -197,6 +199,7 @@ proc g++_init { args } {
global gluefile wrap_flags;
global objdir srcdir
global ALWAYS_CXXFLAGS
+ global CXXFLAGS
global TOOL_EXECUTABLE TOOL_OPTIONS
global GXX_UNDER_TEST
global TESTING_IN_BUILD_TREE
@@ -244,6 +247,10 @@ proc g++_init { args } {
}
}
+ if {![info exists CXXFLAGS]} {
+ set CXXFLAGS ""
+ }
+
set ALWAYS_CXXFLAGS ""
if ![is_remote host] {
diff --git a/gcc/testsuite/lib/profopt.exp b/gcc/testsuite/lib/profopt.exp
index 4d32ff2fdbe..9798c8dea74 100644
--- a/gcc/testsuite/lib/profopt.exp
+++ b/gcc/testsuite/lib/profopt.exp
@@ -130,6 +130,16 @@ proc profopt-execute { src } {
global tool profile_option feedback_option prof_ext perf_ext perf_delta
global verbose
+ # If the host and target systems are not the same, then these
+ # tests will not work, in general, as the compiler writes
+ # absolute paths into the generated binaries when using
+ # profiling.
+ global host_triplet
+ global target_triplet
+ if { $host_triplet != $target_triplet } {
+ return
+ }
+
regsub "^$srcdir/?" $src "" testcase
# If we couldn't rip $srcdir out of `src' then just do the best we can.
# The point is to reduce the unnecessary noise in the logs. Don't strip
@@ -180,6 +190,7 @@ proc profopt-execute { src } {
if { $status == "pass" } {
set basename [file tail $testcase]
set base [file rootname $basename]
+ remote_upload "build" "$base.$prof_ext" "$base.$prof_ext"
set files [glob -nocomplain $base.$prof_ext]
if { $files == "" } {
set status "fail"
diff --git a/gcc/unwind-arm.h b/gcc/unwind-arm.h
index 961e4035490..2b77f2a811a 100644
--- a/gcc/unwind-arm.h
+++ b/gcc/unwind-arm.h
@@ -38,7 +38,7 @@ extern "C" {
#endif
/* We add a prototype for abort here to avoid creating a dependency on
target headers. */
- extern void abort();
+ extern void abort (void);
typedef unsigned _Unwind_Word __attribute__((__mode__(__word__)));
typedef signed _Unwind_Sword __attribute__((__mode__(__word__)));
@@ -246,6 +246,9 @@ extern "C" {
_Unwind_VRS_Set (context, _UVRSC_CORE, regno, _UVRSD_UINT32, &val);
}
+ extern _Unwind_Reason_Code
+ __gnu_unwind_execute (_Unwind_Context * context, __gnu_unwind_state * uws);
+
/* The dwarf unwinder doesn't understand arm/thumb state. We assume the
landing pad uses the same instruction set as the callsite. */
#define _Unwind_SetIP(context, val) \
diff --git a/libstdc++-v3/testsuite/lib/libstdc++.exp b/libstdc++-v3/testsuite/lib/libstdc++.exp
index 403a968f790..3b69a945798 100644
--- a/libstdc++-v3/testsuite/lib/libstdc++.exp
+++ b/libstdc++-v3/testsuite/lib/libstdc++.exp
@@ -210,6 +210,16 @@ proc libstdc++_init { testfile } {
}
}
+ # Tell locale tests where to find the generated .po files.
+ #
+ # ??? At present, testsuite_flags sets LOCALEDIR to a directory in the
+ # build directory. So long as the check_compile and
+ # check_performance scripts it's not safe to modify
+ # testsuite_flags so as not to set LOCALEDIR. So, we must
+ # undefine LOCALEDIR first, so as to avoid a warning from the
+ # compiler.
+ set cxxflags "$cxxflags -ULOCALEDIR -DLOCALEDIR=\".\""
+
if { [target_info needs_status_wrapper]!=""} {
file delete ${objdir}/testglue.o;
set gluefile ${objdir}/testglue.o;
@@ -341,6 +351,16 @@ proc libstdc++_build_support {} {
}
}
+ # Try to build the PO files that are used by some of the locale
+ # tests. If we can't build them, that's OK; it just means that those
+ # tests will fail.
+ foreach lang [list "fr" "de"] {
+ catch {
+ remote_exec "build" "msgfmt" "-o $lang.mo $srcdir/../po/$lang.po"
+ remote_download "host" "$lang.mo" "$lang.mo"
+ }
+ }
+
# Build the support objects.
set source_files \
[list testsuite_abi.cc testsuite_allocator.cc testsuite_hooks.cc]