[ARM] VFP11 denorm erratum workaround in linker
Julian Brown
julian@codesourcery.com
Fri Dec 15 14:16:00 GMT 2006
Hi,
This patch implements a workaround for an erratum in ARM's VFP11
coprocessor. The nature of the erratum is as follows: if a VFP
instruction has denormal operands, the coprocessor must bounce to
support code to handle the operation. In some circumstances,
instructions following the bounced instruction may be issued before this
happens, even if they overwrite one of the previous instruction's operands.
(Note that the erratum is only triggered if full IEEE754 compliance is
enabled by the relevant processor flags, e.g. it doesn't apply in
"RunFast" mode, where denorm values are not bounced to support code. See
ARM documentation for full details).
The erroneous behaviour can be avoided by inserting extra instructions
between the anti-dependent instructions; for scalar code one
intermediate instruction suffices to avoid the erratum, and in vector
code two intermediate instructions must be used.
We've worked around this erratum in the linker: this means code
(particularly third-party static libraries) doesn't need to be
recompiled to invoke the workaround, and if future revisions of the chip
fix the bug, the erratum can simply be switched off and programs
relinked. Solving the problem in the linker also works for hand-written
sequences of VFP code, which a fix in the compiler would not.
GCC at present only outputs scalar code for VFP units, so the default
(pre-ARMv7 architectures) is to fix scalar code. The workaround can be
disabled or selected for vector operations using the linker options:
--vfp11-denorm-fix={none,scalar,vector}
A suitable warning is printed if ARMv7+ objects are being linked, and an
attempt is made to enable the erratum workaround explicitly.
The workaround works by scanning input code sections for
potentially-troublesome code sequences, and replacing them by branches
to a specially-constructed veneer (similar to the way ARM<->Thumb
interworking stubs are created at link-time). The veneer contains the
original instruction plus a branch back to the original subsequent
instruction, which is sufficient to avoid the erratum in either scalar
or vector mode.
Note that we must be able to distinguish between code and data whilst
scanning input sections -- this is done using mapping symbols, which
must now be created for *input* sections, not output sections as
previously. The previous code to create code/data maps for output
sections has been removed, and dependent code adjusted accordingly (only
elf32_arm_write_section, in fact).
BE8 mode needs some special attention -- since mapping tables are now
always created, their existence alone is not enough to justify
code-swapping in elf32_arm_write_section. We must pass an extra argument
to the function (bfd_link_info) to determine whether to byteswap code or
not. We also modify the input-section mapping tables for generated
veneer sections, to make sure that they're byteswapped correctly, if needed.
Tested with cross to arm-none-eabi, and also with the GCC testsuite
(C/C++/libstdc++) with -mfpu=vfp/-mfloat-abi=softfp.
This patch is dependent on a Newlib patch to add the .vfp11_veneer
section to libgloss's linker scripts. That will follow shortly.
OK?
ChangeLog
bfd/
* bfd-in2.h: Regenerate.
* bfd-in.h (bfd_arm_vfp11_fix): New enum. Specify how VFP11
instruction scanning should be done.
(bfd_elf32_arm_init_maps, bfd_elf32_arm_vfp11_erratum_scan)
(bfd_elf32_arm_vfp11_fix_veneer_locations): Add prototypes.
(bfd_elf32_arm_set_target_relocs): Add vfp11 fix type argument to
prototype.
* elf-bfd.h (elf_backend_write_section): Add struct bfd_link_info
argument.
* elf32-arm.c (VFP11_ERRATUM_VENEER_SECTION_NAME)
(VFP11_ERRATUM_VENEER_ENTRY_NAME): Define macros.
(elf32_vfp11_erratum_list): New struct. List of veneers or jumps to
veneers.
(_arm_elf_section_data): Add mapsize, erratumcount, erratumlist.
(elf32_arm_link_hash_table): Add vfp11_erratum_glue_size,
vfp11_fix and num_vfp11_fixes fields.
(elf32_arm_link_hash_table_create): Initialise vfp11_fix,
vfp11_erratum_glue_size, num_vfp11_fixes fields.
(VFP11_ERRATUM_VENEER_SIZE): Define. Size of an (ARM) veneer.
(bfd_elf32_arm_allocate_interworking_sections): Initialise erratum
glue section.
(elf32_arm_section_map_add): Add an code/data mapping symbol entry
to a section's map.
(record_vfp11_erratum_veneer): Create a single veneer, and its
associated symbols.
(bfd_elf32_arm_add_glue_sections_to_bfd): Add vfp11 erratum glue.
(bfd_elf32_arm_init_maps): Initialise mapping symbol table for input
BFDs.
(bfd_elf32_arm_set_vfp11_fix): Set the type of erratum workaround
required.
(bfd_arm_vfp11_pipe): Define VFP11 instruction pipes.
(bfd_arm_vfp11_regno): Recode a register number from a VFP11 insn.
(bfd_arm_vfp11_write_mask): Update write mask according to coded
register number.
(bfd_arm_vfp11_antidependency): New function.
(bfd_arm_vfp11_insn_decode): Decode a VFP11 insn.
(bfd_elf32_arm_vfp11_erratum_scan): Scan the sections of an input
BFD for potential erratum-triggering insns. Record results.
(bfd_elf32_arm_vfp11_fix_veneer_locations): Find out where veneers
and branches to veneers have been placed in virtual memory after
layout.
(bfd_elf32_arm_set_target_relocs): Set vfp11_fix field in global
hash table.
(elf32_arm_output_symbol_hook): Remove.
(elf32_arm_write_section): Output veneers, and branches to veneers.
Use maps from input sections, not output sections, for code
byte-swapping.
* elf32-ppc.c (ppc_elf_write_section): Add dummy link_info argument.
* elf32-score.c (_bfd_score_elf_write_section): Likewise.
* elfxx-mips.c (_bfd_mips_elf_write_section): Likewise.
* elfxx-mips.h (_bfd_mips_elf_write_section): Likewise.
ld/
* 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.
-------------- next part --------------
An embedded and charset-unspecified text was scrubbed...
Name: mainline-vfp11-erratum-fix-11
URL: <https://sourceware.org/pipermail/binutils/attachments/20061215/2b2893f6/attachment.ksh>
More information about the Binutils
mailing list