From c29ef45280f17649d42fb2835076cabf610b66b0 Mon Sep 17 00:00:00 2001
From: Nelson Chu <nelson.chu@sifive.com>
Date: Wed, 4 Dec 2019 18:08:20 +0800
Subject: [PATCH] RISC-V: Fix .p2align is not at smallest instruction.

Just try another solution :)
---
 bfd/elfnn-riscv.c                          |  8 ++++----
 gas/config/tc-riscv.c                      | 13 ++++++++-----
 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/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 +++
 17 files changed, 184 insertions(+), 9 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/elfnn-riscv.c b/bfd/elfnn-riscv.c
index 997f786..cc97a58 100644
--- a/bfd/elfnn-riscv.c
+++ b/bfd/elfnn-riscv.c
@@ -3764,14 +3764,14 @@ _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);
 
+  /* If the number of NOPs is already correct, there's nothing to do.  */
+  if (nop_bytes == rel->r_addend)
+    return TRUE;
+
   /* Write a final RVC NOP if need be.  */
   if (nop_bytes % 4 != 0)
     bfd_put_16 (abfd, RVC_NOP, contents + rel->r_offset + pos);
diff --git a/gas/config/tc-riscv.c b/gas/config/tc-riscv.c
index 055d80c..40c3252 100644
--- a/gas/config/tc-riscv.c
+++ b/gas/config/tc-riscv.c
@@ -2778,15 +2778,18 @@ riscv_frag_align_code (int n)
   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;
-
   /* When not relaxing, riscv_handle_align handles code alignment.  */
   if (!riscv_opts.relax)
     return FALSE;
 
+  /* If we are moving to a smaller alignment than the instruction size,
+     riscv_handle_align handles code alignment.  */
+  if (bytes <= insn_alignment)
+    return FALSE;
+
+  if (frag_now_fix () % insn_alignment != 0)
+    worst_case_bytes = bytes - 2;
+
   nops = frag_more (worst_case_bytes);
 
   ex.X_op = O_constant;
diff --git a/gas/testsuite/gas/riscv/align-2.d b/gas/testsuite/gas/riscv/align-2.d
new file mode 100644
index 0000000..157af5b
--- /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 0000000..87c36ef
--- /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 0000000..097cc96
--- /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 0000000..7cebd33
--- /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 0000000..81914cb
--- /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 0000000..7cebd33
--- /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 0000000..530f9d9
--- /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 0000000..b907643
--- /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/testsuite/ld-riscv-elf/align-1.d b/ld/testsuite/ld-riscv-elf/align-1.d
new file mode 100644
index 0000000..7653d76
--- /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 0000000..61abfd2
--- /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 0000000..b5e0dff
--- /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 0000000..f551c13
--- /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 0000000..b2f8722
--- /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 0000000..63c8cc9
--- /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 7aabbdd..bbdd089 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}
-- 
2.7.4

