From f803aa8eadb24ea7152057584c47648fb02e4716 Mon Sep 17 00:00:00 2001 From: Dr Philipp Tomsich Date: Thu, 30 Oct 2014 10:53:09 +0000 Subject: [PATCH] Remove the artificial limit on code alignment through the use of the fixed part of a fragment for output generation only, which required MAX_MEM_FOR_RS_ALIGN_CODE to be large enough to hold the maximum pad. * config/tc-aarch64.h (MAX_MEM_FOR_RS_ALIGN_CODE): Define to 7. * config/tc-aarch64.c (aarch64_handle_align): Rewrite to handle large alignments with a constant fragment size of MAX_MEM_FOR_RS_ALIGN_CODE. --- gas/ChangeLog | 7 +++++ gas/config/tc-aarch64.c | 67 +++++++++++++++-------------------------- gas/config/tc-aarch64.h | 7 +++-- 3 files changed, 35 insertions(+), 46 deletions(-) diff --git a/gas/ChangeLog b/gas/ChangeLog index a7bd4c34147..8ca1cc132f9 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,10 @@ +2014-10-30 Dr Philipp Tomsich + + * config/tc-aarch64.h (MAX_MEM_FOR_RS_ALIGN_CODE): Define to 7. + * config/tc-aarch64.c (aarch64_handle_align): Rewrite to handle + large alignments with a constant fragment size of + MAX_MEM_FOR_RS_ALIGN_CODE. + 2014-10-29 Nick Clifton * po/uk.po: New Ukranian translation. diff --git a/gas/config/tc-aarch64.c b/gas/config/tc-aarch64.c index 7483f30fc1a..9d5e1d9c79e 100644 --- a/gas/config/tc-aarch64.c +++ b/gas/config/tc-aarch64.c @@ -5825,7 +5825,24 @@ md_section_align (segT segment ATTRIBUTE_UNUSED, valueT size) } /* This is called from HANDLE_ALIGN in write.c. Fill in the contents - of an rs_align_code fragment. */ + of an rs_align_code fragment. + + Here we fill the frag with the appropriate info for padding the + output stream. The resulting frag will consist of a fixed (fr_fix) + and of a repeating (fr_var) part. + + The fixed content is always emitted before the repeating content and + these two parts are used as follows in constructing the output: + - the fixed part will be used to align to a valid instruction word + boundary, in case that we start at a misaligned address; as no + executable instruction can live at the misaligned location, we + simply fill with zeros; + - the variable part will be used to cover the remaining padding and + we fill using the AArch64 NOP instruction. + + Note that the size of a RS_ALIGN_CODE fragment is always 7 to provide + enough storage space for up to 3 bytes for padding the back to a valid + instruction alignment and exactly 4 bytes to store the NOP pattern. */ void aarch64_handle_align (fragS * fragP) @@ -5836,69 +5853,33 @@ aarch64_handle_align (fragS * fragP) int bytes, fix, noop_size; char *p; - const char *noop; if (fragP->fr_type != rs_align_code) return; bytes = fragP->fr_next->fr_address - fragP->fr_address - fragP->fr_fix; p = fragP->fr_literal + fragP->fr_fix; - fix = 0; - - if (bytes > MAX_MEM_FOR_RS_ALIGN_CODE) - bytes &= MAX_MEM_FOR_RS_ALIGN_CODE; #ifdef OBJ_ELF gas_assert (fragP->tc_frag_data.recorded); #endif - noop = aarch64_noop; noop_size = sizeof (aarch64_noop); - fragP->fr_var = noop_size; - if (bytes & (noop_size - 1)) + fix = bytes & (noop_size - 1); + if (fix) { - fix = bytes & (noop_size - 1); #ifdef OBJ_ELF insert_data_mapping_symbol (MAP_INSN, fragP->fr_fix, fragP, fix); #endif memset (p, 0, fix); p += fix; - bytes -= fix; - } - - while (bytes >= noop_size) - { - memcpy (p, noop, noop_size); - p += noop_size; - bytes -= noop_size; - fix += noop_size; + fragP->fr_fix += fix; } - fragP->fr_fix += fix; -} - -/* Called from md_do_align. Used to create an alignment - frag in a code section. */ - -void -aarch64_frag_align_code (int n, int max) -{ - char *p; - - /* We assume that there will never be a requirement - to support alignments greater than x bytes. */ - if (max > MAX_MEM_FOR_RS_ALIGN_CODE) - as_fatal (_ - ("alignments greater than %d bytes not supported in .text sections"), - MAX_MEM_FOR_RS_ALIGN_CODE + 1); - - p = frag_var (rs_align_code, - MAX_MEM_FOR_RS_ALIGN_CODE, - 1, - (relax_substateT) max, - (symbolS *) NULL, (offsetT) n, (char *) NULL); - *p = 0; + if (noop_size) + memcpy (p, aarch64_noop, noop_size); + fragP->fr_var = noop_size; } /* Perform target specific initialisation of a frag. diff --git a/gas/config/tc-aarch64.h b/gas/config/tc-aarch64.h index 3d4ffc57c6f..1fad6ce58b6 100644 --- a/gas/config/tc-aarch64.h +++ b/gas/config/tc-aarch64.h @@ -116,8 +116,9 @@ void aarch64_copy_symbol_attributes (symbolS *, symbolS *); #define TC_CONS_FIX_NEW(f,w,s,e,r) cons_fix_new_aarch64 ((f), (w), (s), (e)) -/* Max code alignment is 32 bytes */ -#define MAX_MEM_FOR_RS_ALIGN_CODE 31 +/* 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 7 /* For frags in code sections we need to record whether they contain code or data. */ @@ -141,7 +142,7 @@ struct aarch64_frag_type #define md_do_align(N, FILL, LEN, MAX, LABEL) \ if (FILL == NULL && (N) != 0 && ! need_pass_2 && subseg_text_p (now_seg)) \ { \ - aarch64_frag_align_code (N, MAX); \ + frag_align_code (N, MAX); \ goto LABEL; \ } -- 2.30.2