summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Waterman <andrew@sifive.com>2016-12-20 14:25:39 -0800
committerAlan Modra <amodra@gmail.com>2016-12-22 00:27:09 +1030
commite5b737de4a22c3099345f2613c106623d7f8d7e7 (patch)
treea8e3e35473256747bc8cb54796b94184f5bb97e3
parentad5bc88245bd8416fd16a2384eb00ec501bcc5e4 (diff)
downloadbinutils-gdb-e5b737de4a22c3099345f2613c106623d7f8d7e7.tar.gz
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.
-rw-r--r--gas/ChangeLog5
-rw-r--r--gas/config/tc-riscv.c22
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 <andrew@sifive.com>
+
+ * 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 <tim@sifive.com>
* 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)