From c6dd86c69582aa64a638c2ddef7cd6a6ae769a71 Mon Sep 17 00:00:00 2001 From: Julian Brown Date: Mon, 29 Jan 2007 16:28:40 +0000 Subject: [PATCH] * NEWS: Mention --vfp11-denorm-fix option. * ld.texinfo: Document above. * emulparams/armelf_linux.sh (OTHER_TEXT_SECTIONS): Add .vfp11_veneer section. * emulparams/armelf.sh (OTHER_TEXT_SECTIONS): Likewise. * emultempl/armelf.em (vfp11_denorm_fix): New static variable. (arm_elf_before_allocation): Call bfd_elf32_arm_set_vfp11_fix, bfd_elf32_arm_init_maps and bfd_elf32_arm_vfp11_erratum_scan. (arm_elf_after_allocation): New function. Call bfd_elf32_arm_vfp11_fix_veneer_locations for all input statements. (arm_elf_create_output_section_statements): Pass vfp11 fix command line option to BFD. (OPTION_VFP11_DENORM_FIX): New option. (PARSE_AND_LIST_LONGOPTS): Handle new option. (PARSE_AND_LIST_OPTIONS): Likewise. (PARSE_AND_LIST_ARGS_CASES): Likewise. (LDEMUL_AFTER_ALLOCATION): Define. --- ld/ChangeLog | 20 ++++++++++++++++ ld/NEWS | 3 +++ ld/emulparams/armelf.sh | 2 +- ld/emulparams/armelf_linux.sh | 2 +- ld/emulparams/armnto.sh | 2 +- ld/emultempl/armelf.em | 44 +++++++++++++++++++++++++++++++++-- ld/ld.texinfo | 30 ++++++++++++++++++++++++ 7 files changed, 98 insertions(+), 5 deletions(-) diff --git a/ld/ChangeLog b/ld/ChangeLog index f3c9cb41f5c..58f095f02a7 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,23 @@ +2006-01-29 Julian Brown + + * NEWS: Mention --vfp11-denorm-fix option. + * ld.texinfo: Document above. + * emulparams/armelf_linux.sh (OTHER_TEXT_SECTIONS): Add + .vfp11_veneer section. + * emulparams/armelf.sh (OTHER_TEXT_SECTIONS): Likewise. + * emultempl/armelf.em (vfp11_denorm_fix): New static variable. + (arm_elf_before_allocation): Call bfd_elf32_arm_set_vfp11_fix, + bfd_elf32_arm_init_maps and bfd_elf32_arm_vfp11_erratum_scan. + (arm_elf_after_allocation): New function. Call + bfd_elf32_arm_vfp11_fix_veneer_locations for all input statements. + (arm_elf_create_output_section_statements): Pass vfp11 fix command + line option to BFD. + (OPTION_VFP11_DENORM_FIX): New option. + (PARSE_AND_LIST_LONGOPTS): Handle new option. + (PARSE_AND_LIST_OPTIONS): Likewise. + (PARSE_AND_LIST_ARGS_CASES): Likewise. + (LDEMUL_AFTER_ALLOCATION): Define. + 2007-01-24 H.J. Lu * ldgram.y (SIZEOF_HEADERS): Remove duplicated one. diff --git a/ld/NEWS b/ld/NEWS index e4ebf947ce5..48e4432aebf 100644 --- a/ld/NEWS +++ b/ld/NEWS @@ -26,6 +26,9 @@ * New switch: --print-gc-sections to list any sections removed by garabge collection. +* ARM: Added --vfp11-denorm-fix option to work around an erratum in current +VFP11 coprocessors. + Changes in 2.17: * Support for the Infineon XC16X has been added by KPIT Cummins Infosystems. diff --git a/ld/emulparams/armelf.sh b/ld/emulparams/armelf.sh index 629228afc98..095ca57e3d2 100644 --- a/ld/emulparams/armelf.sh +++ b/ld/emulparams/armelf.sh @@ -6,7 +6,7 @@ LITTLE_OUTPUT_FORMAT="elf32-littlearm" TEXT_START_ADDR=0x8000 TEMPLATE_NAME=elf32 EXTRA_EM_FILE=armelf -OTHER_TEXT_SECTIONS='*(.glue_7t) *(.glue_7)' +OTHER_TEXT_SECTIONS='*(.glue_7t) *(.glue_7) *(.vfp11_veneer)' OTHER_BSS_SYMBOLS='__bss_start__ = .;' OTHER_BSS_END_SYMBOLS='_bss_end__ = . ; __bss_end__ = . ;' OTHER_END_SYMBOLS='__end__ = . ;' diff --git a/ld/emulparams/armelf_linux.sh b/ld/emulparams/armelf_linux.sh index e7c8025d9a2..e7f301fd37c 100644 --- a/ld/emulparams/armelf_linux.sh +++ b/ld/emulparams/armelf_linux.sh @@ -11,7 +11,7 @@ GENERATE_SHLIB_SCRIPT=yes GENERATE_PIE_SCRIPT=yes DATA_START_SYMBOLS='__data_start = . ;'; -OTHER_TEXT_SECTIONS='*(.glue_7t) *(.glue_7)' +OTHER_TEXT_SECTIONS='*(.glue_7t) *(.glue_7) *(.vfp11_veneer)' OTHER_BSS_SYMBOLS='__bss_start__ = .;' OTHER_BSS_END_SYMBOLS='_bss_end__ = . ; __bss_end__ = . ;' OTHER_END_SYMBOLS='__end__ = . ;' diff --git a/ld/emulparams/armnto.sh b/ld/emulparams/armnto.sh index 6891e63432f..ae0b4bea5bc 100644 --- a/ld/emulparams/armnto.sh +++ b/ld/emulparams/armnto.sh @@ -6,7 +6,7 @@ LITTLE_OUTPUT_FORMAT="elf32-littlearm" TEXT_START_ADDR=0x00100000 TEMPLATE_NAME=elf32 EXTRA_EM_FILE=armelf -OTHER_TEXT_SECTIONS='*(.glue_7t) *(.glue_7)' +OTHER_TEXT_SECTIONS='*(.glue_7t) *(.glue_7) *(.vfp11_veneer)' OTHER_BSS_SYMBOLS='__bss_start__ = .;' OTHER_BSS_END_SYMBOLS='_bss_end__ = . ; __bss_end__ = . ;' OTHER_END_SYMBOLS='__end__ = . ;' diff --git a/ld/emultempl/armelf.em b/ld/emultempl/armelf.em index d52d387f9d1..4522a8bf0c6 100644 --- a/ld/emultempl/armelf.em +++ b/ld/emultempl/armelf.em @@ -35,6 +35,7 @@ static int target1_is_rel = 0${TARGET1_IS_REL}; static char *target2_type = "${TARGET2_TYPE}"; static int fix_v4bx = 0; static int use_blx = 0; +static bfd_arm_vfp11_fix vfp11_denorm_fix = BFD_ARM_VFP11_FIX_DEFAULT; static void gld${EMULATION_NAME}_before_parse (void) @@ -124,6 +125,10 @@ arm_elf_before_allocation (void) bfd_elf32_arm_set_byteswap_code (&link_info, byteswap_code); + /* Choose type of VFP11 erratum fix, or warn if specified fix is unnecessary + due to architecture version. */ + bfd_elf32_arm_set_vfp11_fix (output_bfd, &link_info); + /* We should be able to set the size of the interworking stub section. We can't do it until later if we have dynamic sections, though. */ if (! elf_hash_table (&link_info)->dynamic_sections_created) @@ -131,8 +136,12 @@ arm_elf_before_allocation (void) /* Here we rummage through the found bfds to collect glue information. */ LANG_FOR_EACH_INPUT_STATEMENT (is) { + /* Initialise mapping tables for code/data. */ + bfd_elf32_arm_init_maps (is->the_bfd); + if (!bfd_elf32_arm_process_before_allocation (is->the_bfd, - &link_info)) + &link_info) + || !bfd_elf32_arm_vfp11_erratum_scan (is->the_bfd, &link_info)) /* xgettext:c-format */ einfo (_("Errors encountered processing file %s"), is->filename); } @@ -145,6 +154,22 @@ arm_elf_before_allocation (void) bfd_elf32_arm_allocate_interworking_sections (& link_info); } +static void +arm_elf_after_allocation (void) +{ + /* Call the standard elf routine. */ + after_allocation_default (); + + { + LANG_FOR_EACH_INPUT_STATEMENT (is) + { + /* Figure out where VFP11 erratum veneers (and the labels returning + from same) have been placed. */ + bfd_elf32_arm_vfp11_fix_veneer_locations (is->the_bfd, &link_info); + } + } +} + static void arm_elf_finish (void) { @@ -214,7 +239,7 @@ static void arm_elf_create_output_section_statements (void) { bfd_elf32_arm_set_target_relocs (&link_info, target1_is_rel, target2_type, - fix_v4bx, use_blx); + fix_v4bx, use_blx, vfp11_denorm_fix); } EOF @@ -230,6 +255,7 @@ PARSE_AND_LIST_PROLOGUE=' #define OPTION_TARGET2 305 #define OPTION_FIX_V4BX 306 #define OPTION_USE_BLX 307 +#define OPTION_VFP11_DENORM_FIX 308 ' PARSE_AND_LIST_SHORTOPTS=p @@ -243,6 +269,7 @@ PARSE_AND_LIST_LONGOPTS=' { "target2", required_argument, NULL, OPTION_TARGET2}, { "fix-v4bx", no_argument, NULL, OPTION_FIX_V4BX}, { "use-blx", no_argument, NULL, OPTION_USE_BLX}, + { "vfp11-denorm-fix", required_argument, NULL, OPTION_VFP11_DENORM_FIX}, ' PARSE_AND_LIST_OPTIONS=' @@ -253,6 +280,7 @@ PARSE_AND_LIST_OPTIONS=' fprintf (file, _(" --target2= Specify definition of R_ARM_TARGET2\n")); fprintf (file, _(" --fix-v4bx Rewrite BX rn as MOV pc, rn for ARMv4\n")); fprintf (file, _(" --use-blx Enable use of BLX instructions\n")); + fprintf (file, _(" --vfp11-denorm-fix Specify how to fix VFP11 denorm erratum\n")); ' PARSE_AND_LIST_ARGS_CASES=' @@ -287,12 +315,24 @@ PARSE_AND_LIST_ARGS_CASES=' case OPTION_USE_BLX: use_blx = 1; break; + + case OPTION_VFP11_DENORM_FIX: + if (strcmp (optarg, "none") == 0) + vfp11_denorm_fix = BFD_ARM_VFP11_FIX_NONE; + else if (strcmp (optarg, "scalar") == 0) + vfp11_denorm_fix = BFD_ARM_VFP11_FIX_SCALAR; + else if (strcmp (optarg, "vector") == 0) + vfp11_denorm_fix = BFD_ARM_VFP11_FIX_VECTOR; + else + einfo (_("Unrecognized VFP11 fix type '\''%s'\''.\n"), optarg); + break; ' # We have our own after_open and before_allocation functions, but they call # the standard routines, so give them a different name. LDEMUL_AFTER_OPEN=arm_elf_after_open LDEMUL_BEFORE_ALLOCATION=arm_elf_before_allocation +LDEMUL_AFTER_ALLOCATION=arm_elf_after_allocation LDEMUL_CREATE_OUTPUT_SECTION_STATEMENTS=arm_elf_create_output_section_statements # Replace the elf before_parse function with our own. diff --git a/ld/ld.texinfo b/ld/ld.texinfo index 47e3e9ae200..e4cb6bef460 100644 --- a/ld/ld.texinfo +++ b/ld/ld.texinfo @@ -5489,6 +5489,36 @@ each PLT entry. This should lead to such calls executing slightly faster. This option is enabled implicitly for SymbianOS, so there is no need to specify it if you are using that target. +@cindex VFP11_DENORM_FIX +@kindex --vfp11-denorm-fix +The @samp{--vfp11-denorm-fix} switch enables a link-time workaround for a +bug in certain VFP11 coprocessor hardware, which sometimes allows +instructions with denorm operands (which must be handled by support code) +to have those operands overwritten by subsequent instructions before +the support code can read the intended values. + +The bug may be avoided in scalar mode if you allow at least one +intervening instruction between a VFP11 instruction which uses a register +and another instruction which writes to the same register, or at least two +intervening instructions if vector mode is in use. The bug only affects +full-compliance floating-point mode: you do not need this workaround if +you are using "runfast" mode. Please contact ARM for further details. + +If you know you are using buggy VFP11 hardware, you can +enable this workaround by specifying the linker option +@samp{--vfp-denorm-fix=scalar} if you are using the VFP11 scalar +mode only, or @samp{--vfp-denorm-fix=vector} if you are using +vector mode (the latter also works for scalar code). The default is +@samp{--vfp-denorm-fix=none}. + +If the workaround is enabled, instructions are scanned for +potentially-troublesome sequences, and a veneer is created for each +such sequence which may trigger the erratum. The veneer consists of the +first instruction of the sequence and a branch back to the subsequent +instruction. The original instruction is then replaced with a branch to +the veneer. The extra cycles required to call and return from the veneer +are sufficient to avoid the erratum in both the scalar and vector cases. + @ifclear GENERIC @lowersections @end ifclear -- 2.30.2