On x86, MAX_MEM_FOR_RS_ALIGN_CODE is 35, when the most common
alignment is 2**3 or 2**4, where the max memory required for the
alignment nops is 7 and 15 bytes respectively. So there is some
memory wasted since commit
83d94ae428b1. It's not a large amount,
especially considering that frag overhead on x86_46 is 144 bytes,
but even so I'd rather not be blamed for increasing gas memory usage.
So to reduce the memory we'd like to take the alignment into
consideration when initialising an rs_align_code frag. The only
difficulty here is start_bundle making an rs_align_code frag with an
alignment of zero initially, then later increasing the alignment. We
change that to use the bundle alignment when setting up the frag. I
think that is sufficient as bundle_align_p2 can't change in the middle
of a start_bundle/finish_bundle sequence.
I haven't modified any targets other than x86 in this patch. Most
won't benefit much due to using fairly small MAX_MEM_FOR_RS_ALIGN_CODE.
* read.c (start_bundle): Create rs_align_code frag with
bundle_align_p2 alignment, then set to zero alignment.
(finish_bundle): Adjust comment.
* frags.c (MAX_MEM_FOR_RS_ALIGN_CODE): Pass p2align and max
to macro.
* config/tc-i386.h (HANDLE_ALIGN): Assert that max_bytes is
sufficient for nop padding.
(max_mem_for_rs_align_code): New inline function.
(MAX_MEM_FOR_RS_ALIGN_CODE): Use it.
* config/tc-aarch64.h: Adjust MAX_MEM_FOR_RS_ALIGN_CODE.
* config/tc-alpha.h: Likewise.
* config/tc-arc.h: Likewise.
* config/tc-arm.h: Likewise.
* config/tc-epiphany.h: Likewise.
* config/tc-frv.h: Likewise.
* config/tc-ia64.h: Likewise.
* config/tc-kvx.h: Likewise.
* config/tc-loongarch.h: Likewise.
* config/tc-m32r.h: Likewise.
* config/tc-metag.h: Likewise.
* config/tc-mips.h: Likewise.
* config/tc-nds32.h: Likewise.
* config/tc-ppc.h: Likewise.
* config/tc-riscv.h: Likewise.
* config/tc-rl78.h: Likewise.
* config/tc-rx.h: Likewise.
* config/tc-score.h: Likewise.
* config/tc-sh.h: Likewise.
* config/tc-sparc.h: Likewise.
* config/tc-spu.h: Likewise.
* config/tc-tilegx.h: Likewise.
* config/tc-tilepro.h: Likewise.
* config/tc-visium.h: Likewise.
* config/tc-xtensa.h: Likewise.
#define HANDLE_ALIGN(sec, fragp) aarch64_handle_align (fragp)
/* Max space for a rs_align_code fragment is 3 unaligned bytes
(fr_fix) plus 4 bytes to contain the repeating NOP (fr_var). */
-#define MAX_MEM_FOR_RS_ALIGN_CODE (3 + 4)
+#define MAX_MEM_FOR_RS_ALIGN_CODE(p2align, max) (3 + 4)
#define md_do_align(N, FILL, LEN, MAX, LABEL) \
if (FILL == NULL && (N) != 0 && ! need_pass_2 && subseg_text_p (now_seg)) \
#define HANDLE_ALIGN(sec, fragp) alpha_handle_align (fragp)
extern void alpha_handle_align (struct frag *);
-#define MAX_MEM_FOR_RS_ALIGN_CODE (3 + 4 + 8)
+#define MAX_MEM_FOR_RS_ALIGN_CODE(p2align, max) (3 + 4 + 8)
#ifdef OBJ_ECOFF
#define tc_frob_file_before_adjust() alpha_frob_file_before_adjust ()
/* [ ] is index operator. */
#define NEED_INDEX_OPERATOR
-#define MAX_MEM_FOR_RS_ALIGN_CODE (1+2)
+#define MAX_MEM_FOR_RS_ALIGN_CODE(p2align, max) (1 + 2)
/* HANDLE_ALIGN called after all the assembly has been done,
so we can fill in all the rs_align_code type frags with
#define TC_FRAG_INIT(fragp, max_bytes) arm_init_frag (fragp, max_bytes)
#define TC_ALIGN_ZERO_IS_DEFAULT 1
#define HANDLE_ALIGN(sec, fragp) arm_handle_align (fragp)
-#define MAX_MEM_FOR_RS_ALIGN_CODE (3 + 4)
+#define MAX_MEM_FOR_RS_ALIGN_CODE(p2align, max) (3 + 4)
/* PR gas/19276: COFF/PE segment alignment is already handled in coff_frob_section(). */
#ifndef TE_PE
#define SUB_SEGMENT_ALIGN(SEG, FRCHAIN) \
#define HANDLE_ALIGN(s, f) epiphany_handle_align (f)
extern void epiphany_handle_align (fragS *);
-#define MAX_MEM_FOR_RS_ALIGN_CODE (1 + 2)
+#define MAX_MEM_FOR_RS_ALIGN_CODE(p2align, max) (1 + 2)
#define TARGET_FORMAT "elf32-epiphany"
code actually happens to run, but this is probably too much effort
for little gain. This code is not meant to be run anyway, so just
emit nops. */
-#define MAX_MEM_FOR_RS_ALIGN_CODE (3 + 4)
+#define MAX_MEM_FOR_RS_ALIGN_CODE(p2align, max) (3 + 4)
#define HANDLE_ALIGN(SEC, FRAGP) do \
if ((FRAGP)->fr_type == rs_align_code) \
{ \
#define md_generate_nops(frag, where, amount, control) \
i386_generate_nops ((frag), (where), (amount), (control))
-#define HANDLE_ALIGN(sec, fragP) \
+#define HANDLE_ALIGN(sec, fragP) \
if (fragP->fr_type == rs_align_code) \
{ \
offsetT __count = (fragP->fr_next->fr_address \
- fragP->fr_address \
- fragP->fr_fix); \
if (__count > 0) \
- md_generate_nops (fragP, fragP->fr_literal + fragP->fr_fix, \
- __count, 0); \
+ { \
+ know (fragP->tc_frag_data.max_bytes >= (valueT) __count \
+ || (fragP->tc_frag_data.max_bytes \
+ >= MAX_MEM_FOR_RS_ALIGN_CODE (fragP->fr_offset, \
+ fragP->fr_subtype))); \
+ md_generate_nops (fragP, fragP->fr_literal + fragP->fr_fix, \
+ __count, 0); \
+ } \
}
/* Possible plain nop, branch, twice largest nop less 1.
Yes, the branch might be one byte longer in CODE_16BIT but then the
largest nop is smaller. */
-#define MAX_MEM_FOR_RS_ALIGN_CODE (1 + 5 + 2 * 15 - 1)
-#define MAX_MEM_FOR_RS_SPACE_NOP MAX_MEM_FOR_RS_ALIGN_CODE
+#define MAX_MEM_FOR_RS_SPACE_NOP (1 + 5 + 2 * 15 - 1)
+
+static inline unsigned int
+max_mem_for_rs_align_code (unsigned int p2align, unsigned int max)
+{
+ unsigned int bytes = 1;
+ if (p2align != 0)
+ {
+ bytes = MAX_MEM_FOR_RS_SPACE_NOP;
+ if (bytes > (1ull << p2align) - 1)
+ bytes = (1ull << p2align) - 1;
+ if (max != 0 && bytes > max)
+ bytes = max;
+ }
+ return bytes;
+}
+#define MAX_MEM_FOR_RS_ALIGN_CODE(p2align, max) \
+ max_mem_for_rs_align_code (p2align, max)
/* We want .cfi_* pseudo-ops for generating unwind info. */
#define TARGET_USE_CFIPOP 1
as_bad_where ((FRAGP)->fr_file, (FRAGP)->fr_line, \
_("instruction address is not a multiple of 16"));
-#define MAX_MEM_FOR_RS_ALIGN_CODE (15 + 16)
+#define MAX_MEM_FOR_RS_ALIGN_CODE(p2align, max) (15 + 16)
#define WORKING_DOT_WORD /* don't do broken word processing for now */
/* Enable special handling for the alignment directive. */
extern void kvx_handle_align (fragS *);
#define HANDLE_ALIGN(s, f) kvx_handle_align (f)
-#define MAX_MEM_FOR_RS_ALIGN_CODE (3 + 12 + 16)
+#define MAX_MEM_FOR_RS_ALIGN_CODE(p2align, max) (3 + 12 + 16)
#ifdef OBJ_ELF
#define HANDLE_ALIGN(sec, fragp) loongarch_handle_align (fragp)
extern void loongarch_handle_align (struct frag *);
-#define MAX_MEM_FOR_RS_ALIGN_CODE (3 + 4)
+#define MAX_MEM_FOR_RS_ALIGN_CODE(p2align, max) (3 + 4)
#define elf_tc_final_processing loongarch_elf_final_processing
extern void loongarch_elf_final_processing (void);
extern void m32r_handle_align (fragS *);
#define HANDLE_ALIGN(s, f) m32r_handle_align (f)
-#define MAX_MEM_FOR_RS_ALIGN_CODE (1 + 2 + 4)
+#define MAX_MEM_FOR_RS_ALIGN_CODE(p2align, max) (1 + 2 + 4)
/* Values passed to md_apply_fix don't include the symbol value. */
#define MD_APPLY_SYM_VALUE(FIX) 0
/* Call md_pcrel_from_section(), not md_pcrel_from(). */
#define MD_PCREL_FROM_SECTION(FIX, SEC) md_pcrel_from_section (FIX, SEC)
-#define MAX_MEM_FOR_RS_ALIGN_CODE (3 + 4)
+#define MAX_MEM_FOR_RS_ALIGN_CODE(p2align, max) (3 + 4)
#define HANDLE_ALIGN(sec, fragp) metag_handle_align (fragp)
extern void metag_handle_align (struct frag *);
extern void mips_handle_align (struct frag *);
#define HANDLE_ALIGN(sec, fragp) mips_handle_align (fragp)
-#define MAX_MEM_FOR_RS_ALIGN_CODE (3 + 4)
+#define MAX_MEM_FOR_RS_ALIGN_CODE(p2align, max) (3 + 4)
struct insn_label_list;
struct mips_segment_info {
#define GAS_SORT_RELOCS 1
/* Values passed to md_apply_fix don't include the symbol value. */
#define MD_APPLY_SYM_VALUE(FIX) 0
-#define MAX_MEM_FOR_RS_ALIGN_CODE (1 + 2 + 4)
+#define MAX_MEM_FOR_RS_ALIGN_CODE(p2align, max) (1 + 2 + 4)
#define HANDLE_ALIGN(s, f) nds32_handle_align (f)
#undef DIFF_EXPR_OK /* They should be fixed in linker. */
#define md_relax_frag(segment, fragP, stretch) nds32_relax_frag (segment, fragP, stretch)
/* We don't need to handle .word strangely. */
#define WORKING_DOT_WORD
-#define MAX_MEM_FOR_RS_ALIGN_CODE 8
+#define MAX_MEM_FOR_RS_ALIGN_CODE(p2align, max) 8
#define HANDLE_ALIGN(SEC, FRAGP) \
if ((FRAGP)->fr_type == rs_align_code) \
ppc_handle_align (SEC, FRAGP);
extern void riscv_handle_align (fragS *);
#define HANDLE_ALIGN(s, f) riscv_handle_align (f)
-#define MAX_MEM_FOR_RS_ALIGN_CODE (3 + 4)
+#define MAX_MEM_FOR_RS_ALIGN_CODE(p2align, max) (3 + 4)
/* The ISA of the target may change based on command-line arguments. */
#define TARGET_FORMAT riscv_target_format ()
#define RELOC_EXPANSION_POSSIBLE 1
#define MAX_RELOC_EXPANSION 8
-#define MAX_MEM_FOR_RS_ALIGN_CODE 8
+#define MAX_MEM_FOR_RS_ALIGN_CODE(p2align, max) 8
#define HANDLE_ALIGN(SEC, FRAG) rl78_handle_align (FRAG)
extern void rl78_handle_align (fragS *);
goto around; \
}
-#define MAX_MEM_FOR_RS_ALIGN_CODE 8
+#define MAX_MEM_FOR_RS_ALIGN_CODE(p2align, max) 8
#define HANDLE_ALIGN(SEC, FRAG) rx_handle_align (FRAG)
extern void rx_handle_align (fragS *);
#define DIFF_EXPR_OK
#define RELOC_EXPANSION_POSSIBLE
#define MAX_RELOC_EXPANSION 2
-#define MAX_MEM_FOR_RS_ALIGN_CODE (3 + 4)
+#define MAX_MEM_FOR_RS_ALIGN_CODE(p2align, max) (3 + 4)
#define md_undefined_symbol(name) NULL
#define HANDLE_ALIGN(sec, frag) sh_handle_align (frag)
extern void sh_handle_align (fragS *);
-#define MAX_MEM_FOR_RS_ALIGN_CODE (1 + 2)
+#define MAX_MEM_FOR_RS_ALIGN_CODE(p2align, max) (1 + 2)
/* We need to force out some relocations when relaxing. */
#define TC_FORCE_RELOCATION(fix) sh_force_relocation (fix)
#define HANDLE_ALIGN(sec, fragp) sparc_handle_align (fragp)
extern void sparc_handle_align (struct frag *);
-#define MAX_MEM_FOR_RS_ALIGN_CODE (3 + 4 + 4)
+#define MAX_MEM_FOR_RS_ALIGN_CODE(p2align, max) (3 + 4 + 4)
#define DIFF_EXPR_OK /* foo-. gets turned into PC relative relocs */
extern void spu_handle_align (fragS *);
#define HANDLE_ALIGN(sec, frag) spu_handle_align (frag)
-#define MAX_MEM_FOR_RS_ALIGN_CODE (7 + 8)
+#define MAX_MEM_FOR_RS_ALIGN_CODE(p2align, max) (7 + 8)
#endif /* TC_SPU */
#define HANDLE_ALIGN(sec, fragp) tilegx_handle_align (fragp)
extern void tilegx_handle_align (struct frag *);
-#define MAX_MEM_FOR_RS_ALIGN_CODE (7 + 8)
+#define MAX_MEM_FOR_RS_ALIGN_CODE(p2align, max) (7 + 8)
struct tilegx_operand;
#define TC_FIX_TYPE const struct tilegx_operand *
#define HANDLE_ALIGN(sec, fragp) tilepro_handle_align (fragp)
extern void tilepro_handle_align (struct frag *);
-#define MAX_MEM_FOR_RS_ALIGN_CODE (7 + 8)
+#define MAX_MEM_FOR_RS_ALIGN_CODE(p2align, max) (7 + 8)
struct tilepro_operand;
#define TC_FIX_TYPE const struct tilepro_operand *
#define tc_fix_adjustable(FIXP) visium_fix_adjustable (FIXP)
extern bool visium_fix_adjustable (struct fix *);
-#define MAX_MEM_FOR_RS_ALIGN_CODE (4 + 1)
+#define MAX_MEM_FOR_RS_ALIGN_CODE(p2align, max) (4 + 1)
#define HANDLE_ALIGN(SEC, FRAGP) \
if ((FRAGP)->fr_type == rs_align_code) \
visium_handle_align (FRAGP);
#define DATA_SECTION_NAME xtensa_section_rename (".data")
#define BSS_SECTION_NAME xtensa_section_rename (".bss")
#define HANDLE_ALIGN(sec, fragP) xtensa_handle_align (fragP)
-#define MAX_MEM_FOR_RS_ALIGN_CODE 1
+#define MAX_MEM_FOR_RS_ALIGN_CODE(p2align, max) 1
/* The renumber_section function must be mapped over all the sections
the alignment code. Needs to be large enough to hold any fixed size
prologue plus the replicating portion. */
#ifndef MAX_MEM_FOR_RS_ALIGN_CODE
-# define MAX_MEM_FOR_RS_ALIGN_CODE 1
+# define MAX_MEM_FOR_RS_ALIGN_CODE(p2align, max) 1
#endif
void
{
char *p;
- p = frag_var (rs_align_code, MAX_MEM_FOR_RS_ALIGN_CODE, 1,
+ p = frag_var (rs_align_code, MAX_MEM_FOR_RS_ALIGN_CODE (alignment, max), 1,
(relax_substateT) max, (symbolS *) 0,
(offsetT) alignment, (char *) 0);
*p = NOP_OPCODE;
{
fragS *frag = frag_now;
- frag_align_code (0, 0);
+ frag_align_code (bundle_align_p2, 0);
while (frag->fr_type != rs_align_code)
frag = frag->fr_next;
gas_assert (frag != frag_now);
+ /* Set initial alignment to zero. */
+ frag->fr_offset = 0;
+
return frag;
}
if (size > 1)
{
- /* If there is more than a single byte, then we need to set up the
- alignment frag. Otherwise we leave it at its initial state from
- calling frag_align_code (0, 0), so that it does nothing. */
+ /* If there is more than a single byte, then we need to set up
+ the alignment frag. Otherwise we leave it at its initial
+ state with zero alignment so that it does nothing. */
frag->fr_offset = bundle_align_p2;
frag->fr_subtype = size - 1;
}