MIPS16/GAS: Fix delay slot filling across frags

Fix an assertion failure like:

test.s: Assembler messages:
test.s:3: Internal error!
Assertion failure in append_insn at .../gas/config/tc-mips.c:7523.
Please report this bug.

triggered by assembling MIPS16 code like:

hello:
	addiu	$4, $4, 4
	jr	$31

with the generation of a listing file enabled, e.g.:

$ as -mips16 -O2 -aln=test.lst

The cause of the problem is the lack of support for moving instructions
across frags in MIPS16 jump swapping, which triggers more easily with
listing enabled as in that case every instruction gets placed in its own
frag.  It would trigger even with listing disabled though if the
instruction to swap a MIPS16 jump with was unfortunately enough placed
as last in a frag that became full.

This scenario is already handled correctly with branch swapping in
regular MIPS and microMIPS code, so reuse it for MIPS16 code as well,
and now that all MIPS16 handling has become the same as the regular MIPS
and microMIPS cases remove MIPS16 special casing altogether.

This effectively complements:

commit 464ab0e55ade01d2bb0b4fa45c429af7a2f85a26
Author: Maciej W. Rozycki <macro@linux-mips.org>
Date:   Mon Aug 6 20:33:00 2012 +0000

<https://sourceware.org/ml/binutils/2012-08/msg00043.html>, ("MIPS/GAS:
Correct microMIPS branch swapping assertion") for the MIPS16 case.

The assertion itself was introduced with:

commit 1e91584932efd70020c8c98037d0cb93a0552a20
Author: Richard Sandiford <rdsandiford@googlemail.com>
Date:   Wed Mar 9 09:17:02 2005 +0000

<https://sourceware.org/ml/binutils/2005-03/msg00217.html>, ("Rework
MIPS nop-insertion code, add -mfix-vr4130 [5/11]"), but its introduction
merely noted our existing lack of support for MIPS16 jump swapping
across frags.

	gas/
	* config/tc-mips.c (append_insn) <APPEND_SWAP>: Do not special
	case MIPS16 handling.
	* testsuite/gas/mips/branch-swap-3.d: New test.
	* testsuite/gas/mips/branch-swap-4.d: New test.
	* testsuite/gas/mips/mips16@branch-swap-3.d: New test.
	* testsuite/gas/mips/mips16@branch-swap-4.d: New test.
	* testsuite/gas/mips/micromips@branch-swap-3.d: New test.
	* testsuite/gas/mips/micromips@branch-swap-4.d: New test.
	* testsuite/gas/mips/branch-swap-3.s: New test source.
	* testsuite/gas/mips/mips.exp: Run the new tests.
diff --git a/gas/ChangeLog b/gas/ChangeLog
index 4459273..149cc4c 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -1,3 +1,17 @@
+2016-06-30  Matthew Fortune <Matthew.Fortune@imgtec.com>
+	    Maciej W. Rozycki  <macro@imgtec.com>
+
+	* config/tc-mips.c (append_insn) <APPEND_SWAP>: Do not special
+	case MIPS16 handling.
+	* testsuite/gas/mips/branch-swap-3.d: New test.
+	* testsuite/gas/mips/branch-swap-4.d: New test.
+	* testsuite/gas/mips/mips16@branch-swap-3.d: New test.
+	* testsuite/gas/mips/mips16@branch-swap-4.d: New test.
+	* testsuite/gas/mips/micromips@branch-swap-3.d: New test.
+	* testsuite/gas/mips/micromips@branch-swap-4.d: New test.
+	* testsuite/gas/mips/branch-swap-3.s: New test source.
+	* testsuite/gas/mips/mips.exp: Run the new tests.
+
 2016-06-30  Maciej W. Rozycki  <macro@imgtec.com>
 
 	* config/tc-mips.c (append_insn): Simplify non-MIPS16 branch
diff --git a/gas/config/tc-mips.c b/gas/config/tc-mips.c
index 77ba0c9..50e5844 100644
--- a/gas/config/tc-mips.c
+++ b/gas/config/tc-mips.c
@@ -7518,13 +7518,8 @@
     case APPEND_SWAP:
       {
 	struct mips_cl_insn delay = history[0];
-	if (mips_opts.mips16)
-	  {
-	    know (delay.frag == ip->frag);
-	    move_insn (ip, delay.frag, delay.where);
-	    move_insn (&delay, ip->frag, ip->where + insn_length (ip));
-	  }
-	else if (relaxed_branch || delay.frag != ip->frag)
+
+	if (relaxed_branch || delay.frag != ip->frag)
 	  {
 	    /* Add the delay slot instruction to the end of the
 	       current frag and shrink the fixed part of the
diff --git a/gas/testsuite/gas/mips/branch-swap-3.d b/gas/testsuite/gas/mips/branch-swap-3.d
new file mode 100644
index 0000000..6bb3668
--- /dev/null
+++ b/gas/testsuite/gas/mips/branch-swap-3.d
@@ -0,0 +1,38 @@
+#objdump: -dr -M reg-names=numeric
+#as: -32 -O2 -aln=branch-swap-lst.lst
+#name: MIPS branch swapping with assembler listing
+#source: branch-swap-3.s
+
+# Check delay slot filling with a listing file works
+
+.*: +file format .*mips.*
+
+Disassembly of section \.text:
+
+[0-9a-f]+ <test>:
+[ 0-9a-f]+:	0c000000 	jal	0 <test>
+[ 	]*[0-9a-f]+: R_MIPS_26	func
+[ 0-9a-f]+:	00408025 	move	\$16,\$2
+[ 0-9a-f]+:	0c000000 	jal	0 <test>
+[ 	]*[0-9a-f]+: R_MIPS_26	func
+[ 0-9a-f]+:	26300001 	addiu	\$16,\$17,1
+[ 0-9a-f]+:	0c000000 	jal	0 <test>
+[ 	]*[0-9a-f]+: R_MIPS_26	func
+[ 0-9a-f]+:	26300001 	addiu	\$16,\$17,1
+[ 0-9a-f]+:	0c000000 	jal	0 <test>
+[ 	]*[0-9a-f]+: R_MIPS_26	func
+[ 0-9a-f]+:	26303fff 	addiu	\$16,\$17,16383
+[ 0-9a-f]+:	0c000000 	jal	0 <test>
+[ 	]*[0-9a-f]+: R_MIPS_26	func
+[ 0-9a-f]+:	26303fff 	addiu	\$16,\$17,16383
+[ 0-9a-f]+:	03e0000[89] 	jr	\$31
+[ 0-9a-f]+:	00408025 	move	\$16,\$2
+[ 0-9a-f]+:	03e0000[89] 	jr	\$31
+[ 0-9a-f]+:	26300001 	addiu	\$16,\$17,1
+[ 0-9a-f]+:	03e0000[89] 	jr	\$31
+[ 0-9a-f]+:	26300001 	addiu	\$16,\$17,1
+[ 0-9a-f]+:	03e0000[89] 	jr	\$31
+[ 0-9a-f]+:	26303fff 	addiu	\$16,\$17,16383
+[ 0-9a-f]+:	03e0000[89] 	jr	\$31
+[ 0-9a-f]+:	26303fff 	addiu	\$16,\$17,16383
+	\.\.\.
diff --git a/gas/testsuite/gas/mips/branch-swap-3.s b/gas/testsuite/gas/mips/branch-swap-3.s
new file mode 100644
index 0000000..2a31e7b
--- /dev/null
+++ b/gas/testsuite/gas/mips/branch-swap-3.s
@@ -0,0 +1,30 @@
+	.text
+test:
+	move	$16, $2
+	jal	func
+	addiu	$16, $17, 1
+	jal	func
+	addiu	$16, $17, foo
+	jal	func
+	addiu	$16, $17, 0x3fff
+	jal	func
+	addiu	$16, $17, bar
+	jal	func
+
+	move	$16, $2
+	jr	$31
+	addiu	$16, $17, 1
+	jr	$31
+	addiu	$16, $17, foo
+	jr	$31
+	addiu	$16, $17, 0x3fff
+	jr	$31
+	addiu	$16, $17, bar
+	jr	$31
+
+	.set	foo, 1
+	.set	bar, 0x3fff
+
+	# Force some (non-delay-slot) zero bytes, to make 'objdump' print ...
+	.space	16
+	.align	4, 0
diff --git a/gas/testsuite/gas/mips/branch-swap-4.d b/gas/testsuite/gas/mips/branch-swap-4.d
new file mode 100644
index 0000000..ed25a79
--- /dev/null
+++ b/gas/testsuite/gas/mips/branch-swap-4.d
@@ -0,0 +1,5 @@
+#objdump: -dr -M reg-names=numeric
+#as: -32 -O2
+#name: MIPS branch swapping without assembler listing
+#source: branch-swap-3.s
+#dump: branch-swap-3.d
diff --git a/gas/testsuite/gas/mips/micromips@branch-swap-3.d b/gas/testsuite/gas/mips/micromips@branch-swap-3.d
new file mode 100644
index 0000000..3ed6349
--- /dev/null
+++ b/gas/testsuite/gas/mips/micromips@branch-swap-3.d
@@ -0,0 +1,40 @@
+#objdump: -dr -M reg-names=numeric
+#as: -32 -O2 -aln=branch-swap-lst.lst
+#name: MIPS branch swapping with assembler listing
+#source: branch-swap-3.s
+
+# Check delay slot filling with a listing file works (microMIPS)
+
+.*: +file format .*mips.*
+
+Disassembly of section \.text:
+
+[0-9a-f]+ <test>:
+[ 0-9a-f]+:	0e02      	move	\$16,\$2
+[ 0-9a-f]+:	f400 0000 	jal	0 <test>
+[ 	]*[0-9a-f]+: R_MICROMIPS_26_S1	func
+[ 0-9a-f]+:	0000 0000 	nop
+[ 0-9a-f]+:	6c10      	addiu	\$16,\$17,1
+[ 0-9a-f]+:	f400 0000 	jal	0 <test>
+[ 	]*[0-9a-f]+: R_MICROMIPS_26_S1	func
+[ 0-9a-f]+:	0000 0000 	nop
+[ 0-9a-f]+:	f400 0000 	jal	0 <test>
+[ 	]*[0-9a-f]+: R_MICROMIPS_26_S1	func
+[ 0-9a-f]+:	3211 0001 	addiu	\$16,\$17,1
+[ 0-9a-f]+:	f400 0000 	jal	0 <test>
+[ 	]*[0-9a-f]+: R_MICROMIPS_26_S1	func
+[ 0-9a-f]+:	3211 3fff 	addiu	\$16,\$17,16383
+[ 0-9a-f]+:	f400 0000 	jal	0 <test>
+[ 	]*[0-9a-f]+: R_MICROMIPS_26_S1	func
+[ 0-9a-f]+:	3211 3fff 	addiu	\$16,\$17,16383
+[ 0-9a-f]+:	459f      	jr	\$31
+[ 0-9a-f]+:	0e02      	move	\$16,\$2
+[ 0-9a-f]+:	459f      	jr	\$31
+[ 0-9a-f]+:	6c10      	addiu	\$16,\$17,1
+[ 0-9a-f]+:	459f      	jr	\$31
+[ 0-9a-f]+:	3211 0001 	addiu	\$16,\$17,1
+[ 0-9a-f]+:	459f      	jr	\$31
+[ 0-9a-f]+:	3211 3fff 	addiu	\$16,\$17,16383
+[ 0-9a-f]+:	459f      	jr	\$31
+[ 0-9a-f]+:	3211 3fff 	addiu	\$16,\$17,16383
+	\.\.\.
diff --git a/gas/testsuite/gas/mips/micromips@branch-swap-4.d b/gas/testsuite/gas/mips/micromips@branch-swap-4.d
new file mode 100644
index 0000000..63fe675
--- /dev/null
+++ b/gas/testsuite/gas/mips/micromips@branch-swap-4.d
@@ -0,0 +1,5 @@
+#objdump: -dr -M reg-names=numeric
+#as: -32 -O2
+#name: MIPS branch swapping without assembler listing
+#source: branch-swap-3.s
+#dump: micromips@branch-swap-3.d
diff --git a/gas/testsuite/gas/mips/mips.exp b/gas/testsuite/gas/mips/mips.exp
index 4f5651b..a83750e 100644
--- a/gas/testsuite/gas/mips/mips.exp
+++ b/gas/testsuite/gas/mips/mips.exp
@@ -575,6 +575,9 @@
 	    "MIPS branch swapping ($count)"
     }
 
+    run_dump_test_arches "branch-swap-3" [mips_arch_list_all]
+    run_dump_test_arches "branch-swap-4" [mips_arch_list_all]
+
     run_dump_test "branch-section-1"
     run_dump_test "branch-section-2"
     run_dump_test "branch-section-3"
diff --git a/gas/testsuite/gas/mips/mips16@branch-swap-3.d b/gas/testsuite/gas/mips/mips16@branch-swap-3.d
new file mode 100644
index 0000000..5164778
--- /dev/null
+++ b/gas/testsuite/gas/mips/mips16@branch-swap-3.d
@@ -0,0 +1,44 @@
+#objdump: -dr -M reg-names=numeric
+#as: -32 -O2 -aln=branch-swap-lst.lst
+#name: MIPS branch swapping with assembler listing
+#source: branch-swap-3.s
+
+# Check delay slot filling with a listing file works (MIPS16)
+
+.*: +file format .*mips.*
+
+Disassembly of section \.text:
+
+[0-9a-f]+ <test>:
+[ 0-9a-f]+:	1800 0000 	jal	0 <test>
+[ 	]*[0-9a-f]+: R_MIPS16_26	func
+[ 0-9a-f]+:	6702      	move	\$16,\$2
+[ 0-9a-f]+:	1800 0000 	jal	0 <test>
+[ 	]*[0-9a-f]+: R_MIPS16_26	func
+[ 0-9a-f]+:	4101      	addiu	\$16,\$17,1
+[ 0-9a-f]+:	4101      	addiu	\$16,\$17,1
+[ 0-9a-f]+:	1800 0000 	jal	0 <test>
+[ 	]*[0-9a-f]+: R_MIPS16_26	func
+[ 0-9a-f]+:	6500      	nop
+[ 0-9a-f]+:	f7f7 410f 	addiu	\$16,\$17,16383
+[ 0-9a-f]+:	1800 0000 	jal	0 <test>
+[ 	]*[0-9a-f]+: R_MIPS16_26	func
+[ 0-9a-f]+:	6500      	nop
+[ 0-9a-f]+:	f7f7 410f 	addiu	\$16,\$17,16383
+[ 0-9a-f]+:	1800 0000 	jal	0 <test>
+[ 	]*[0-9a-f]+: R_MIPS16_26	func
+[ 0-9a-f]+:	6500      	nop
+[ 0-9a-f]+:	e820      	jr	\$31
+[ 0-9a-f]+:	6702      	move	\$16,\$2
+[ 0-9a-f]+:	e820      	jr	\$31
+[ 0-9a-f]+:	4101      	addiu	\$16,\$17,1
+[ 0-9a-f]+:	4101      	addiu	\$16,\$17,1
+[ 0-9a-f]+:	e820      	jr	\$31
+[ 0-9a-f]+:	6500      	nop
+[ 0-9a-f]+:	f7f7 410f 	addiu	\$16,\$17,16383
+[ 0-9a-f]+:	e820      	jr	\$31
+[ 0-9a-f]+:	6500      	nop
+[ 0-9a-f]+:	f7f7 410f 	addiu	\$16,\$17,16383
+[ 0-9a-f]+:	e820      	jr	\$31
+[ 0-9a-f]+:	6500      	nop
+	\.\.\.
diff --git a/gas/testsuite/gas/mips/mips16@branch-swap-4.d b/gas/testsuite/gas/mips/mips16@branch-swap-4.d
new file mode 100644
index 0000000..f10603a
--- /dev/null
+++ b/gas/testsuite/gas/mips/mips16@branch-swap-4.d
@@ -0,0 +1,5 @@
+#objdump: -dr -M reg-names=numeric
+#as: -32 -O2
+#name: MIPS branch swapping without assembler listing
+#source: branch-swap-3.s
+#dump: mips16@branch-swap-3.d