This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
Re: [PATCH] RISC-V: Fix .p2align is not at smallest instruction
- From: "Palmer Dabbelt via binutils" <binutils at sourceware dot org>
- To: kuanlinchentw at gmail dot com
- Cc: binutils at sourceware dot org
- Date: Tue, 10 Dec 2019 18:25:14 -0800 (PST)
- Subject: Re: [PATCH] RISC-V: Fix .p2align is not at smallest instruction
- Reply-to: Palmer Dabbelt <palmerdabbelt at google dot com>
On Tue, 03 Dec 2019 00:15:41 PST (-0800), kuanlinchentw@gmail.com wrote:
Hi,
As far as I know, RISC-V compilers (LLVM & GCC) doesn't mix code and data
in the same section. But we cannot avoid users mixing them in manual assembly
code.
Example:
.text
.globl main
.option norvc
.option relax
main:
nop
.byte 0x99
.byte 0x99
.byte 0x99
.p2align 1
nop
After assembling:
00000000 <main>:
0: 00000013 nop
4: 9999 andi a1,a1,-26
6: 1399 addi t2,t2,-26
8: 0000 unimp
The second nop doesn't align to 2-byte alignment.
BTW, the test case ld/testsuite/ld-riscv-elf/align-1.d is for
commit(ed0816bd936492aa7dc00e4fbbf8ff8de1253854).
I'm not sure exactly what the issue is here, but after poking this a bit I'm
seeing some issues. One issue is that I see some sperious NOPs being included
at the end of input sections that aren't being deleted, for examlpe:
$ cat /home/palmerdabbelt/life/riscv/binutils-gdb/gas/testsuite/gas/riscv/align-6.s && ./install/bin/riscv64-unknown-linux-gnu-as /home/palmerdabbelt/life/riscv/binutils-gdb/gas/testsuite/gas/riscv/align-6.s -o align-6.o && ./install/bin/riscv64-unknown-linux-gnu-objdump -dr align-6.o && ./install/bin/riscv64-unknown-linux-gnu-ld align-6.o -o align-6 && riscv64-linux-gnu-objdump -d align-6
.text
.globl _start
.globl aligned1
.globl aligned2
.option relax
.option norvc
_start:
.p2align 4
aligned1:
xori x0, x0, 1
.byte 0xAA
.byte 0xAB
.byte 0xAC
.byte 0xAD
.p2align 3
aligned2:
xori x0, x0, 2
xori x0, x0, 3
xori x0, x0, 4
xori x0, x0, 5
align-6.o: file format elf64-littleriscv
Disassembly of section .text:
0000000000000000 <_start>:
...
0: R_RISCV_ALIGN *ABS*+0xc
000000000000000c <aligned1>:
c: 00104013 xori zero,zero,1
10: abaa fsd fa0,464(sp)
12: adac fsd fa1,88(a1)
14: 0000 unimp
14: R_RISCV_ALIGN *ABS*+0x4
...
0000000000000018 <aligned2>:
18: 00204013 xori zero,zero,2
1c: 00304013 xori zero,zero,3
20: 00404013 xori zero,zero,4
24: 00504013 xori zero,zero,5
28: 00000013 nop
2c: 00000013 nop
align-6: file format elf64-littleriscv
Disassembly of section .text:
0000000000010080 <_start>:
10080: 00104013 xori zero,zero,1
10084: abaa fsd fa0,464(sp)
10086: adac fsd fa1,88(a1)
0000000000010088 <aligned2>:
10088: 00204013 xori zero,zero,2
1008c: 00304013 xori zero,zero,3
10090: 00404013 xori zero,zero,4
10094: 00504013 xori zero,zero,5
10098: 00000013 nop
1009c: 00000013 nop
Depnding on exactly how I mess with the constants I can get different amounts
of excess bytes at the end of the linked executable.
bfd/ChangeLog:
* elfnn-riscv.c (_bfd_riscv_relax_align): Fill nops for alignment.
* elfxx-riscv.c (howto_table): Modify size of R_RISCV_ALIGN.
gas/ChangeLog:
* config/tc-riscv.c (md_apply_fix): Adjust BFD_RELOC_RISCV_ALIGN addend.
* (riscv_frag_align_code): New the alignment fragments.
* (riscv_handle_align): Fill rs_align_code fragments.
* testsuite/gas/riscv/align-2.d: New test.
* testsuite/gas/riscv/align-2.s: New test.
* testsuite/gas/riscv/align-3.d: New test.
* testsuite/gas/riscv/align-3.s: New test.
* testsuite/gas/riscv/align-4.d: New test.
* testsuite/gas/riscv/align-4.s: New test.
* testsuite/gas/riscv/align-5.d: New test.
* testsuite/gas/riscv/align-5.s: New test.
ld/ChangeLog:
* testsuite/ld-riscv-elf/align-1.d: New test.
* testsuite/ld-riscv-elf/align-1.s New test.
* testsuite/ld-riscv-elf/align-2.d New test.
* testsuite/ld-riscv-elf/align-2.s New test.
* testsuite/ld-riscv-elf/align-3.d New test.
* testsuite/ld-riscv-elf/align-3.s New test.
* testsuite/ld-riscv-elf/ld-riscv-elf.exp: Add align-1, align-2 and
align-3.
From e5c85fb1978c71df0a0c94e8f5d96aac05068970 Mon Sep 17 00:00:00 2001
From: Kuan-Lin Chen <rufus@andestech.com>
Date: Wed, 27 Nov 2019 10:25:36 +0800
Subject: [PATCH] RISC-V: Fix .p2align is not at smallest instruction
alignment.
As far as I know, RISC-V compilers (LLVM & GCC) doesn't mix code and data
in the same section. But we cannot avoid users mixing them in manual assembly
code.
Example:
.text
.globl main
.option norvc
.option relax
main:
nop
.byte 0x99
.byte 0x99
.byte 0x99
.p2align 1
nop
After assembling:
00000000 <main>:
0: 00000013 nop
4: 9999 andi a1,a1,-26
6: 1399 addi t2,t2,-26
8: 0000 unimp
The second nop doesn't align to 2-byte alignment.
BTW, the test case ld/testsuite/ld-riscv-elf/align-1.d is for
commit(ed0816bd936492aa7dc00e4fbbf8ff8de1253854).
bfd/ChangeLog:
* elfnn-riscv.c (_bfd_riscv_relax_align): Fill nops for alignment.
* elfxx-riscv.c (howto_table): Modify size of R_RISCV_ALIGN.
gas/ChangeLog:
* config/tc-riscv.c (md_apply_fix): Adjust BFD_RELOC_RISCV_ALIGN addend.
* (riscv_frag_align_code): New the alignment fragments.
* (riscv_handle_align): Fill rs_align_code fragments.
* testsuite/gas/riscv/align-2.d: New test.
* testsuite/gas/riscv/align-2.s: New test.
* testsuite/gas/riscv/align-3.d: New test.
* testsuite/gas/riscv/align-3.s: New test.
* testsuite/gas/riscv/align-4.d: New test.
* testsuite/gas/riscv/align-4.s: New test.
* testsuite/gas/riscv/align-5.d: New test.
* testsuite/gas/riscv/align-5.s: New test.
ld/ChangeLog:
* testsuite/ld-riscv-elf/align-1.d: New test.
* testsuite/ld-riscv-elf/align-1.s New test.
* testsuite/ld-riscv-elf/align-2.d New test.
* testsuite/ld-riscv-elf/align-2.s New test.
* testsuite/ld-riscv-elf/align-3.d New test.
* testsuite/ld-riscv-elf/align-3.s New test.
* testsuite/ld-riscv-elf/ld-riscv-elf.exp: Add align-1, align-2 and
align-3.
---
bfd/ChangeLog | 5 +
bfd/elfnn-riscv.c | 8 +-
bfd/elfxx-riscv.c | 2 +-
gas/ChangeLog | 15 +++
gas/config/tc-riscv.c | 103 +++++++++++----------
gas/testsuite/gas/riscv/align-2.d | 13 +++
gas/testsuite/gas/riscv/align-2.s | 11 +++
gas/testsuite/gas/riscv/align-3.d | 13 +++
gas/testsuite/gas/riscv/align-3.s | 8 ++
gas/testsuite/gas/riscv/align-4.d | 14 +++
gas/testsuite/gas/riscv/align-4.s | 8 ++
gas/testsuite/gas/riscv/align-5.d | 13 +++
gas/testsuite/gas/riscv/align-5.s | 8 ++
ld/ChangeLog | 11 +++
ld/testsuite/ld-riscv-elf/align-1.d | 17 ++++
ld/testsuite/ld-riscv-elf/align-1.s | 10 ++
ld/testsuite/ld-riscv-elf/align-2.d | 17 ++++
ld/testsuite/ld-riscv-elf/align-2.s | 10 ++
ld/testsuite/ld-riscv-elf/align-3.d | 17 ++++
ld/testsuite/ld-riscv-elf/align-3.s | 10 ++
ld/testsuite/ld-riscv-elf/ld-riscv-elf.exp | 3 +
21 files changed, 262 insertions(+), 54 deletions(-)
create mode 100644 gas/testsuite/gas/riscv/align-2.d
create mode 100644 gas/testsuite/gas/riscv/align-2.s
create mode 100644 gas/testsuite/gas/riscv/align-3.d
create mode 100644 gas/testsuite/gas/riscv/align-3.s
create mode 100644 gas/testsuite/gas/riscv/align-4.d
create mode 100644 gas/testsuite/gas/riscv/align-4.s
create mode 100644 gas/testsuite/gas/riscv/align-5.d
create mode 100644 gas/testsuite/gas/riscv/align-5.s
create mode 100644 ld/testsuite/ld-riscv-elf/align-1.d
create mode 100644 ld/testsuite/ld-riscv-elf/align-1.s
create mode 100644 ld/testsuite/ld-riscv-elf/align-2.d
create mode 100644 ld/testsuite/ld-riscv-elf/align-2.s
create mode 100644 ld/testsuite/ld-riscv-elf/align-3.d
create mode 100644 ld/testsuite/ld-riscv-elf/align-3.s
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 4a0852e577..6161da2171 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,8 @@
+2019-11-28 Kuan-Lin Chen <kuanlinchentw@gmail.com>
+
+ * elfnn-riscv.c (_bfd_riscv_relax_align): Fill nops for alignment.
+ * elfxx-riscv.c (howto_table): Modify size of R_RISCV_ALIGN.
+
2019-11-27 Alan Modra <amodra@gmail.com>
PR 23652
diff --git a/bfd/elfnn-riscv.c b/bfd/elfnn-riscv.c
index 997f786602..aa6e88f411 100644
--- a/bfd/elfnn-riscv.c
+++ b/bfd/elfnn-riscv.c
@@ -3764,10 +3764,6 @@ _bfd_riscv_relax_align (bfd *abfd, asection *sec,
/* Delete the reloc. */
rel->r_info = ELFNN_R_INFO (0, R_RISCV_NONE);
- /* If the number of NOPs is already correct, there's nothing to do. */
- if (nop_bytes == rel->r_addend)
- return TRUE;
-
/* Write as many RISC-V NOPs as we need. */
for (pos = 0; pos < (nop_bytes & -4); pos += 4)
bfd_put_32 (abfd, RISCV_NOP, contents + rel->r_offset + pos);
@@ -3776,6 +3772,10 @@ _bfd_riscv_relax_align (bfd *abfd, asection *sec,
if (nop_bytes % 4 != 0)
bfd_put_16 (abfd, RVC_NOP, contents + rel->r_offset + pos);
+ /* If the number of NOPs is already correct, there's nothing to do. */
+ if (nop_bytes == rel->r_addend)
+ return TRUE;
+
/* Delete the excess bytes. */
return riscv_relax_delete_bytes (abfd, sec, rel->r_offset + nop_bytes,
rel->r_addend - nop_bytes, link_info);
diff --git a/bfd/elfxx-riscv.c b/bfd/elfxx-riscv.c
index 245717f70f..15a4f32f8c 100644
--- a/bfd/elfxx-riscv.c
+++ b/bfd/elfxx-riscv.c
@@ -634,7 +634,7 @@ static reloc_howto_type howto_table[] =
addend rounded up to the next power of two. */
HOWTO (R_RISCV_ALIGN, /* type */
0, /* rightshift */
- 2, /* size */
+ 3, /* size */
Does this change the ABI? I'm a bit worried about this, because one way to fix
our alignment issues would be to introduce another relocation and deprecate
R_RISCV_ALIGN.
0, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
diff --git a/gas/ChangeLog b/gas/ChangeLog
index 09991524da..ec5191bf16 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -1,3 +1,18 @@
+2019-11-27 Kuan-Lin Chen <kuanlinchentw@gmail.com>
+
+ * config/tc-riscv.c (md_apply_fix): Adjust BFD_RELOC_RISCV_ALIGN
+ addend.
+ * (riscv_frag_align_code): New the alignment fragments.
+ * (riscv_handle_align): Fill rs_align_code fragments.
+ * testsuite/gas/riscv/align-2.d: New test.
+ * testsuite/gas/riscv/align-2.s: New test.
+ * testsuite/gas/riscv/align-3.d: New test.
+ * testsuite/gas/riscv/align-3.s: New test.
+ * testsuite/gas/riscv/align-4.d: New test.
+ * testsuite/gas/riscv/align-4.s: New test.
+ * testsuite/gas/riscv/align-5.d: New test.
+ * testsuite/gas/riscv/align-5.s: New test.
+
2019-11-25 Andrew Pinski <apinski@marvell.com>
* config/tc-aarch64.c (md_begin): Use correct
diff --git a/gas/config/tc-riscv.c b/gas/config/tc-riscv.c
index e50505138e..a1f4881dbd 100644
--- a/gas/config/tc-riscv.c
+++ b/gas/config/tc-riscv.c
@@ -2581,6 +2581,8 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
break;
case BFD_RELOC_RISCV_ALIGN:
+ if (fixP->fx_frag->fr_var >= 2)
+ fixP->fx_addnumber += 2;
break;
What's this trying to do? It seem like it would cause leakage (or, I guess, is
more trying to work around some leakage).
default:
@@ -2764,39 +2766,43 @@ riscv_make_nops (char *buf, bfd_vma bytes)
md_number_to_chars (buf + i, RISCV_NOP, 4);
}
-/* Called from md_do_align. Used to create an alignment frag in a
- code section by emitting a worst-case NOP sequence that the linker
- will later relax to the correct number of NOPs. We can't compute
- the correct alignment now because of other linker relaxations. */
+/* Called from md_do_align. Insert a ALIGN relocation for linker to
+ relax and compute the correct alignment.
+ TODO: handle the reset arguments of .p2align that linker can relax these
+ types. */
bfd_boolean
riscv_frag_align_code (int n)
{
+ expressionS exp;
bfd_vma bytes = (bfd_vma) 1 << n;
+ bfd_vma alignment_power = riscv_opts.rvc ? 1 : 2;
bfd_vma insn_alignment = riscv_opts.rvc ? 2 : 4;
bfd_vma worst_case_bytes = bytes - insn_alignment;
- char *nops;
- expressionS ex;
-
- /* If we are moving to a smaller alignment than the instruction size, then no
- alignment is required. */
- if (bytes <= insn_alignment)
- return TRUE;
+ fragS* fragP = frag_now;
+ /* Set the address at the optimizable begining. */
+ unsigned fragP_fix = (frag_now_fix() + 1) >> 1 << 1;
/* When not relaxing, riscv_handle_align handles code alignment. */
if (!riscv_opts.relax)
return FALSE;
- nops = frag_more (worst_case_bytes);
-
- ex.X_op = O_constant;
- ex.X_add_number = worst_case_bytes;
-
- riscv_make_nops (nops, worst_case_bytes);
-
- fix_new_exp (frag_now, nops - frag_now->fr_literal, 0,
- &ex, FALSE, BFD_RELOC_RISCV_ALIGN);
+ /* If we are moving to a smaller alignment than the instruction size,
+ riscv_handle_align handles code alignment. */
+ if (bytes <= insn_alignment)
+ return FALSE;
+ /* Make sure the current alignment is align to insntruction alignment. */
+ frag_align_code (alignment_power, 0);
+
+ /* Insert a ALIGN relocation for linker to remove the redandunt nops.
+ Locate the relocation in the rs_align_code frag instead of frag_now,
+ because we want linker to know the whole size of the alignment. */
+ exp.X_op = O_constant;
+ /* Just set the worst value temporarily. */
+ exp.X_add_number = worst_case_bytes;
+ fix_new_exp (fragP, fragP_fix, 0, &exp, 0, BFD_RELOC_RISCV_ALIGN);
+ frag_more (worst_case_bytes);
return TRUE;
}
@@ -2805,38 +2811,37 @@ riscv_frag_align_code (int n)
void
riscv_handle_align (fragS *fragP)
{
- switch (fragP->fr_type)
- {
- case rs_align_code:
- /* When relaxing, riscv_frag_align_code handles code alignment. */
- if (!riscv_opts.relax)
- {
- bfd_signed_vma bytes = (fragP->fr_next->fr_address
- - fragP->fr_address - fragP->fr_fix);
- /* We have 4 byte uncompressed nops. */
- bfd_signed_vma size = 4;
- bfd_signed_vma excess = bytes % size;
- char *p = fragP->fr_literal + fragP->fr_fix;
-
- if (bytes <= 0)
- break;
+ bfd_signed_vma bytes ;
- /* Insert zeros or compressed nops to get 4 byte alignment. */
- if (excess)
- {
- riscv_make_nops (p, excess);
- fragP->fr_fix += excess;
- p += excess;
- }
+ if (fragP->fr_type != rs_align_code)
+ return;
- /* Insert variable number of 4 byte uncompressed nops. */
- riscv_make_nops (p, size);
- fragP->fr_var = size;
- }
- break;
+ bytes = fragP->fr_next->fr_address - fragP->fr_address - fragP->fr_fix;
+ /* We have 4 byte uncompressed nops. */
+ bfd_signed_vma size = 4;
+ bfd_signed_vma excess = bytes % size;
+ char *p = fragP->fr_literal + fragP->fr_fix;
- default:
- break;
+ if (bytes <= 0)
+ return;
+
+ /* Insert zeros or compressed nops to get 4 byte alignment. */
+ if (excess)
+ {
+ riscv_make_nops (p, excess);
+ fragP->fr_fix += excess;
+ p += excess;
+ if (excess >= 2)
+ fragP->fr_var = 2;
+ }
+
+ if (bytes > size)
+ {
+ /* After this function, the frag will be set to fr_fill. We only
+ insert one 4 byte nop here. The reset space will be filled in
+ write_contents. */
+ riscv_make_nops (p, size);
+ fragP->fr_var = size;
}
}
diff --git a/gas/testsuite/gas/riscv/align-2.d b/gas/testsuite/gas/riscv/align-2.d
new file mode 100644
index 0000000000..157af5bbaf
--- /dev/null
+++ b/gas/testsuite/gas/riscv/align-2.d
@@ -0,0 +1,13 @@
+#as: -march=rv32ic
+#objdump: -dr
+
+.*:[ ]+file format .*
+
+
+Disassembly of section .text:
+
+0+000 <main>:
+[^:]+:[ ]+00000013[ ]+nop
+[^:]+:[ ]+9999.*
+[^:]+:[ ]+0099.*
+[^:]+8:[ ]+00000013[ ]+nop
diff --git a/gas/testsuite/gas/riscv/align-2.s b/gas/testsuite/gas/riscv/align-2.s
new file mode 100644
index 0000000000..87c36efd41
--- /dev/null
+++ b/gas/testsuite/gas/riscv/align-2.s
@@ -0,0 +1,11 @@
+.text
+.globl main
+.option norvc
+.option relax
+main:
+ nop
+ .byte 0x99
+ .byte 0x99
+ .byte 0x99
+.p2align 1
+ nop
diff --git a/gas/testsuite/gas/riscv/align-3.d b/gas/testsuite/gas/riscv/align-3.d
new file mode 100644
index 0000000000..097cc9626d
--- /dev/null
+++ b/gas/testsuite/gas/riscv/align-3.d
@@ -0,0 +1,13 @@
+#as: -march=rv32i
+#objdump: -dr
+
+.*:[ ]+file format .*
+
+
+Disassembly of section .text:
+
+0+000 <main>:
+[^:]+:[ ]+00000013[ ]+nop
+[^:]+:[ ]+9999.*
+.*
+[^:]+8:[ ]+00000013[ ]+nop
diff --git a/gas/testsuite/gas/riscv/align-3.s b/gas/testsuite/gas/riscv/align-3.s
new file mode 100644
index 0000000000..7cebd33255
--- /dev/null
+++ b/gas/testsuite/gas/riscv/align-3.s
@@ -0,0 +1,8 @@
+.text
+.globl main
+.option relax
+main:
+ nop
+ .short 0x9999
+.p2align 2
+ nop
diff --git a/gas/testsuite/gas/riscv/align-4.d b/gas/testsuite/gas/riscv/align-4.d
new file mode 100644
index 0000000000..81914cb430
--- /dev/null
+++ b/gas/testsuite/gas/riscv/align-4.d
@@ -0,0 +1,14 @@
+#as: -march=rv32ic
+#objdump: -dr
+
+.*:[ ]+file format .*
+
+
+Disassembly of section .text:
+
+0+000 <main>:
+[^:]+:[ ]+0001[ ]+nop
+[^:]+:[ ]+9999.*
+.*
+[^:]+4: R_RISCV_ALIGN[ ]+\*ABS\*\+0x2
+[^:]+6:[ ]+0001[ ]+nop
diff --git a/gas/testsuite/gas/riscv/align-4.s b/gas/testsuite/gas/riscv/align-4.s
new file mode 100644
index 0000000000..7cebd33255
--- /dev/null
+++ b/gas/testsuite/gas/riscv/align-4.s
@@ -0,0 +1,8 @@
+.text
+.globl main
+.option relax
+main:
+ nop
+ .short 0x9999
+.p2align 2
+ nop
diff --git a/gas/testsuite/gas/riscv/align-5.d b/gas/testsuite/gas/riscv/align-5.d
new file mode 100644
index 0000000000..530f9d9a64
--- /dev/null
+++ b/gas/testsuite/gas/riscv/align-5.d
@@ -0,0 +1,13 @@
+#as: -march=rv32i
+#objdump: -dr
+
+.*:[ ]+file format .*
+
+
+Disassembly of section .text:
+
+0+000 <main>:
+[^:]+:[ ]+00000013[ ]+nop
+[^:]+:[ ]+9999.*
+[^:]+:[ ]+1111.*
+[^:]+8:[ ]+00000013[ ]+nop
diff --git a/gas/testsuite/gas/riscv/align-5.s b/gas/testsuite/gas/riscv/align-5.s
new file mode 100644
index 0000000000..b907643e08
--- /dev/null
+++ b/gas/testsuite/gas/riscv/align-5.s
@@ -0,0 +1,8 @@
+.text
+.globl main
+.option relax
+main:
+ nop
+ .short 0x9999
+.p2align 2, 0x11
+ nop
diff --git a/ld/ChangeLog b/ld/ChangeLog
index 969ab78035..54abd7955c 100644
--- a/ld/ChangeLog
+++ b/ld/ChangeLog
@@ -1,3 +1,14 @@
+2019-11-27 Kuan-Lin Chen <kuanlinchentw@gmail.com>
+
+ * testsuite/ld-riscv-elf/align-1.d: New test.
+ * testsuite/ld-riscv-elf/align-1.s New test.
+ * testsuite/ld-riscv-elf/align-2.d New test.
+ * testsuite/ld-riscv-elf/align-2.s New test.
+ * testsuite/ld-riscv-elf/align-3.d New test.
+ * testsuite/ld-riscv-elf/align-3.s New test.
+ * testsuite/ld-riscv-elf/ld-riscv-elf.exp: Add align-1, align-2 and
+ align-3.
+
2019-11-26 Martin Liska <mliska@suse.cz>
* scripttempl/arclinux.sc: Add .text.sorted.* which is sorted
diff --git a/ld/testsuite/ld-riscv-elf/align-1.d b/ld/testsuite/ld-riscv-elf/align-1.d
new file mode 100644
index 0000000000..7653d76a81
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/align-1.d
@@ -0,0 +1,17 @@
+#source: align-1.s
+#as: -march=rv32ic
+#ld: -melf32lriscv
+#objdump: -d
+
+.*:[ ]+file format .*
+
+Disassembly of section .text:
+
+.* <_start>:
+.*:[ ]+8086[ ]+mv[ ]+ra,ra
+.*:[ ]+810a[ ]+mv[ ]+sp,sp
+
+.* <rvc_boundry>:
+.*:[ ]+00000013[ ]+nop
+.*:[ ]+00018193[ ]+mv[ ]+gp,gp
+#pass
diff --git a/ld/testsuite/ld-riscv-elf/align-1.s b/ld/testsuite/ld-riscv-elf/align-1.s
new file mode 100644
index 0000000000..61abfd24fd
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/align-1.s
@@ -0,0 +1,10 @@
+.global _start
+.option rvc
+_start:
+ mv x1, x1
+ mv x2, x2
+.align 2
+rvc_boundry:
+.option norvc
+.align 3
+ mv x3, x3
diff --git a/ld/testsuite/ld-riscv-elf/align-2.d b/ld/testsuite/ld-riscv-elf/align-2.d
new file mode 100644
index 0000000000..b5e0dfffa6
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/align-2.d
@@ -0,0 +1,17 @@
+#source: align-2.s
+#as: -march=rv32i
+#ld: -melf32lriscv
+#objdump: -d
+
+.*:[ ]+file format .*
+
+Disassembly of section .text:
+
+.* <_start>:
+.*:[ ]+00010093[ ]+mv[ ]+ra,sp
+.*:[ ]+9999[ ]+.*
+.*:[ ]+[0-9]{4}.*
+.*:[ ]+00010093[ ]+mv[ ]+ra,sp
+.*:[ ]+00000013[ ]+nop
+.*:[ ]+00010093[ ]+mv[ ]+ra,sp
+#pass
diff --git a/ld/testsuite/ld-riscv-elf/align-2.s b/ld/testsuite/ld-riscv-elf/align-2.s
new file mode 100644
index 0000000000..f551c1347b
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/align-2.s
@@ -0,0 +1,10 @@
+.text
+.globl _start
+.option norvc
+_start:
+ mv x1, x2
+ .short 0x9999
+.p2align 2
+ mv x1, x2
+.p2align 3
+ mv x1, x2
diff --git a/ld/testsuite/ld-riscv-elf/align-3.d b/ld/testsuite/ld-riscv-elf/align-3.d
new file mode 100644
index 0000000000..b2f872210c
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/align-3.d
@@ -0,0 +1,17 @@
+#source: align-3.s
+#as: -march=rv32i
+#ld: -melf32lriscv
+#objdump: -d
+
+.*:[ ]+file format .*
+
+Disassembly of section .text:
+
+.* <_start>:
+.*[08]:[ ]+9999[ ]+.*
+.*
+.*
+.*[08]:[ ]+00010093[ ]+mv[ ]+ra,sp
+.*:[ ]+00010093[ ]+mv[ ]+ra,sp
+.*:[ ]+00010093[ ]+mv[ ]+ra,sp
+#pass
diff --git a/ld/testsuite/ld-riscv-elf/align-3.s b/ld/testsuite/ld-riscv-elf/align-3.s
new file mode 100644
index 0000000000..63c8cc99f4
--- /dev/null
+++ b/ld/testsuite/ld-riscv-elf/align-3.s
@@ -0,0 +1,10 @@
+.text
+.globl _start
+.option norvc
+_start:
+.p2align 3
+ .short 0x9999
+.p2align 3
+ mv x1, x2
+ mv x1, x2
+ mv x1, x2
diff --git a/ld/testsuite/ld-riscv-elf/ld-riscv-elf.exp b/ld/testsuite/ld-riscv-elf/ld-riscv-elf.exp
index 7aabbdd641..bbdd089bec 100644
--- a/ld/testsuite/ld-riscv-elf/ld-riscv-elf.exp
+++ b/ld/testsuite/ld-riscv-elf/ld-riscv-elf.exp
@@ -38,6 +38,9 @@ if [istarget "riscv*-*-*"] {
run_dump_test "attr-merge-priv-spec"
run_dump_test "attr-merge-arch-failed-01"
run_dump_test "attr-merge-stack-align-failed"
+ run_dump_test "align-1"
+ run_dump_test "align-2"
+ run_dump_test "align-3"
run_ld_link_tests {
{ "Weak reference 32" "-T weakref.ld -melf32lriscv" ""
"-march=rv32i -mabi=ilp32" {weakref32.s}