This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
Re: [PATCH 3/5] i386: Align branches within a fixed boundary
On Tue, Dec 3, 2019 at 11:02 AM H.J. Lu <hjl.tools@gmail.com> wrote:
>
> Add 3 command-line options to align branches within a fixed boundary
> with segment prefixes or NOPs:
>
> 1. -malign-branch-boundary=NUM aligns branches within NUM byte boundary.
> 2. -malign-branch=TYPE[+TYPE...] specifies types of branches to align.
> The supported branches are:
> a. Conditional jump.
> b. Fused conditional jump.
> c. Unconditional jump.
> d. Call.
> e. Ret.
> f. Indirect jump and call.
> 3. -malign-branch-prefix-size=NUM aligns branches with NUM segment
> prefixes per instruction.
>
> 3 new rs_machine_dependent frag types are added:
>
> 1. BRANCH_PADDING. The variable size frag to insert NOP before branch.
> 2. BRANCH_PREFIX. The variable size frag to insert segment prefixes to
> an instruction. The choices of prefixes are:
> a. Use the existing segment prefix if there is one.
> b. Use CS segment prefix in 64-bit mode.
> c. In 32-bit mode, use SS segment prefix with ESP/EBP base register
> and use DS segment prefix without ESP/EBP base register.
> 3. FUSED_JCC_PADDING. The variable size frag to insert NOP before fused
> conditional jump.
>
> The new rs_machine_dependent frags aren't inserted if the previous item
> is a prefix or a constant directive, which may be used to hardcode an
> instruction, since there is no clear instruction boundary. NOP padding
> is disabled before tls_get_addr calls to keep TLS instruction sequence
> unchanged.
>
> md_estimate_size_before_relax() and i386_generic_table_relax_frag() are
> used to handled BRANCH_PADDING, BRANCH_PREFIX and FUSED_JCC_PADDING frags.
> i386_generic_table_relax_frag() grows or shrinks sizes of segment prefix
> and NOP to align the next branch frag:
>
> 1. First try to add segment prefixes to instructions before a branch.
> 2. If there is no sufficient room to add segment prefixes, NOP will be
> inserted before a branch.
>
> * config/tc-i386.c (_i386_insn): Add has_gotpc_reloc.
> (tls_get_addr): New.
> (last_insn): New.
> (align_branch_power): New.
> (align_branch_kind): New.
> (align_branch): New.
> (MAX_FUSED_JCC_PADDING_SIZE): New.
> (align_branch_prefix_size): New.
> (BRANCH_PADDING): New.
> (BRANCH_PREFIX): New.
> (FUSED_JCC_PADDING): New.
> (i386_generate_nops): Support BRANCH_PADDING and FUSED_JCC_PADDING.
> (md_begin): Abort if align_branch_prefix_size <
> MAX_FUSED_JCC_PADDING_SIZE.
> (md_assemble): Set last_insn.
> (maybe_fused_with_jcc_p): New.
> (add_fused_jcc_padding_frag_p): New.
> (add_branch_prefix_frag_p): New.
> (add_branch_padding_frag_p): New.
> (output_insn): Generate a BRANCH_PADDING, FUSED_JCC_PADDING or
> BRANCH_PREFIX frag and terminate each frag to align branches.
> (output_disp): Set i.has_gotpc_reloc to TRUE for GOTPC
> relocation.
> (output_imm): Likewise.
> (i386_next_non_empty_frag): New.
> (i386_next_jcc_frag): New.
> (i386_classify_machine_dependent_frag): New.
> (i386_branch_padding_size): New.
> (i386_generic_table_relax_frag): New.
> (md_estimate_size_before_relax): Handle COND_JUMP_PADDING,
> FUSED_JCC_PADDING and COND_JUMP_PREFIX frags.
> (md_convert_frag): Handle BRANCH_PADDING, BRANCH_PREFIX and
> FUSED_JCC_PADDING frags.
> (OPTION_MALIGN_BRANCH_BOUNDARY): New.
> (OPTION_MALIGN_BRANCH_PREFIX_SIZE): New.
> (OPTION_MALIGN_BRANCH): New.
> (md_longopts): Add -malign-branch-boundary=,
> -malign-branch-prefix-size= and -malign-branch=.
> (md_parse_option): Handle -malign-branch-boundary=,
> -malign-branch-prefix-size= and -malign-branch=.
> (md_show_usage): Display -malign-branch-boundary=,
> -malign-branch-prefix-size= and -malign-branch=.
> (i386_target_format): Set tls_get_addr.
> (i386_cons_worker): New.
> * config/tc-i386.h (i386_cons_worker): New.
> (md_cons_worker): New.
> (i386_generic_table_relax_frag): New.
> (md_generic_table_relax_frag): New.
> (i386_tc_frag_data): Add u, padding_address, length,
> max_prefix_length, prefix_length, default_prefix, cmp_size,
> classified and branch_type.
> (TC_FRAG_INIT): Initialize u, padding_address, base_opcode,
> length, max_prefix_length, prefix_length, default_prefix,
> cmp_size and classified.
> * doc/c-i386.texi: Document -malign-branch-boundary=,
> -malign-branch-prefix-size= and -malign-branch=.
Please ignore this one.
--
H.J.