diff options
author | Andrew Waterman <andrew@sifive.com> | 2016-12-20 14:25:39 -0800 |
---|---|---|
committer | Alan Modra <amodra@gmail.com> | 2016-12-22 00:27:09 +1030 |
commit | e5b737de4a22c3099345f2613c106623d7f8d7e7 (patch) | |
tree | a8e3e35473256747bc8cb54796b94184f5bb97e3 | |
parent | ad5bc88245bd8416fd16a2384eb00ec501bcc5e4 (diff) | |
download | gdb-e5b737de4a22c3099345f2613c106623d7f8d7e7.zip gdb-e5b737de4a22c3099345f2613c106623d7f8d7e7.tar.gz gdb-e5b737de4a22c3099345f2613c106623d7f8d7e7.tar.bz2 |
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/ChangeLog | 5 | ||||
-rw-r--r-- | gas/config/tc-riscv.c | 22 |
2 files changed, 21 insertions, 6 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog index 616fd09..de6e5d5 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 8c78f61..8c732f0 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) |