From e5b737de4a22c3099345f2613c106623d7f8d7e7 Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Tue, 20 Dec 2016 14:25:39 -0800 Subject: [PATCH] Support aligning text section from odd addresses Previously, the alignment directives were not correctly supported in the text section when current alignment was only 1 byte (i.e., when the address was odd). Since there are no 1-byte instructions in RISC-V, this patch resolves the bug by writing a zero byte to obtain 2-byte alignment, at which point a 2-byte NOP can be used to obtain 4-byte alignment. Resolves https://github.com/riscv/riscv-gnu-toolchain/issues/205 * config/tc-riscv.c (riscv_make_nops): Emit 2-byte NOPs. (riscv_frag_align_code): Correct frag_align_code arg. --- gas/ChangeLog | 5 +++++ gas/config/tc-riscv.c | 22 ++++++++++++++++------ 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/gas/ChangeLog b/gas/ChangeLog index 616fd09ba8b..de6e5d5e13a 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,8 @@ +2016-12-21 Andrew Waterman + + * config/tc-riscv.c (riscv_make_nops): Emit 2-byte NOPs. + (riscv_frag_align_code): Correct frag_align_code arg. + 2016-12-21 Tim Newsome * config/tc-riscv.c (riscv_pre_output_hook): Remove const from diff --git a/gas/config/tc-riscv.c b/gas/config/tc-riscv.c index 8c78f614a53..8c732f0a8da 100644 --- a/gas/config/tc-riscv.c +++ b/gas/config/tc-riscv.c @@ -2190,14 +2190,20 @@ riscv_make_nops (char *buf, bfd_vma bytes) { bfd_vma i = 0; - if (bytes % 4 == 2) + /* RISC-V instructions cannot begin or end on odd addresses, so this case + means we are not within a valid instruction sequence. It is thus safe + to use a zero byte, even though that is not a valid instruction. */ + if (bytes % 2 == 1) + buf[i++] = 0; + + /* Use at most one 2-byte NOP. */ + if ((bytes - i) % 4 == 2) { - md_number_to_chars (buf, RVC_NOP, 2); + md_number_to_chars (buf + i, RVC_NOP, 2); i += 2; } - gas_assert ((bytes - i) % 4 == 0); - + /* Fill the remainder with 4-byte NOPs. */ for ( ; i < bytes; i += 4) md_number_to_chars (buf + i, RISCV_NOP, 4); } @@ -2210,8 +2216,12 @@ riscv_make_nops (char *buf, bfd_vma bytes) bfd_boolean riscv_frag_align_code (int n) { - bfd_vma bytes = (bfd_vma)1 << n; - bfd_vma min_text_alignment = riscv_opts.rvc ? 2 : 4; + bfd_vma bytes = (bfd_vma) 1 << n; + bfd_vma min_text_alignment_order = riscv_opts.rvc ? 1 : 2; + bfd_vma min_text_alignment = (bfd_vma) 1 << min_text_alignment_order; + + /* First, get back to minimal alignment. */ + frag_align_code (min_text_alignment_order, 0); /* When not relaxing, riscv_handle_align handles code alignment. */ if (!riscv_opts.relax) -- 2.30.2