summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMaciej W. Rozycki <macro@imgtec.com>2017-03-02 01:24:15 +0000
committerMaciej W. Rozycki <macro@imgtec.com>2017-03-02 01:44:07 +0000
commit9875b36538d35f2292ddc3bb5e7c60e1582aa087 (patch)
tree9de303f12626d4b6f99406f109f1f73e6072f04e
parent673cff9b8b3105f74ce97c202a0727f9e83e56e6 (diff)
GAS: Fix bogus "attempt to move .org backwards" relaxation errors
Fix a commit 6afe8e98a664 ("internal error for backwards .org"), <https://www.sourceware.org/ml/binutils/2008-06/msg00212.html>, GAS regression that caused legitimate code to fail assembly with an "attempt to move .org backwards" error. For example with the `mips-linux' target we get: $ cat org.s .set mips16 la $2, foo .org 0x1000 .align 2 foo: .half 0 $ as -o org.o org.s org.s: Assembler messages: org.s:3: Error: attempt to move .org backwards $ where the location pointer is obviously not moved backwards with `.org'. The cause is positive `stretch' in relaxation due to a PC-relative ADDIU instruction (produced from the LA macro used) getting expanded from 2 to 4 bytes as `foo' is noticed to be out of range for the short encoding. This in turn triggers logic in `relax_segment' which concludes in the processing of an `rs_org' frag produced that the location pointer is moved backwards while in fact only the amount to space forward to the location requested has shrunk, resulting in a negative growth of the frag. Correct the bad logic then and instead verify that the fixed part of an `rs_org' frag has not overrun the location requested, as per the comment already included with the error message: /* Growth may be negative, but variable part of frag cannot have fewer than 0 chars. That is, we can't .org backwards. */ which accurately describes the regression scenario. Move the comment ahead the conditional noted, for clarity. Add generic and MIPS test cases for the `.org' pseudo-op, including the test case discussed though not integrated with the offending commit in particular, adjusted to work across all targets. gas/ * write.c (relax_segment) <rs_org>: Only bail out if the fixed part of the frag has overrun the location requested. * testsuite/gas/all/org-1.d: New test. * testsuite/gas/all/org-2.d: New test. * testsuite/gas/all/org-3.d: New test. * testsuite/gas/all/org-4.d: New test. * testsuite/gas/all/org-5.d: New test. * testsuite/gas/all/org-6.d: New test. * testsuite/gas/all/org-1.l: New stderr output. * testsuite/gas/all/org-2.l: New stderr output. * testsuite/gas/all/org-3.l: New stderr output. * testsuite/gas/all/org-1.s: New test source. * testsuite/gas/all/org-2.s: New test source. * testsuite/gas/all/org-3.s: New test source. * testsuite/gas/all/org-4.s: New test source. * testsuite/gas/all/org-5.s: New test source. * testsuite/gas/all/org-6.s: New test source. * testsuite/gas/all/gas.exp: Run the new tests. * testsuite/gas/mips/org-1.d: New test. * testsuite/gas/mips/org-2.d: New test. * testsuite/gas/mips/org-3.d: New test. * testsuite/gas/mips/org-4.d: New test. * testsuite/gas/mips/org-5.d: New test. * testsuite/gas/mips/org-6.d: New test. * testsuite/gas/mips/org-7.d: New test. * testsuite/gas/mips/org-8.d: New test. * testsuite/gas/mips/org-9.d: New test. * testsuite/gas/mips/org-10.d: New test. * testsuite/gas/mips/org-11.d: New test. * testsuite/gas/mips/org-12.d: New test. * testsuite/gas/mips/org-1.l: New stderr output. * testsuite/gas/mips/org-4.l: New stderr output. * testsuite/gas/mips/org-5.l: New stderr output. * testsuite/gas/mips/org-6.l: New stderr output. * testsuite/gas/mips/org-10.l: New stderr output. * testsuite/gas/mips/org-1.s: New test source. * testsuite/gas/mips/org-2.s: New test source. * testsuite/gas/mips/org-3.s: New test source. * testsuite/gas/mips/org-4.s: New test source. * testsuite/gas/mips/org-5.s: New test source. * testsuite/gas/mips/org-6.s: New test source. * testsuite/gas/mips/org-7.s: New test source. * testsuite/gas/mips/org-8.s: New test source. * testsuite/gas/mips/org-9.s: New test source. * testsuite/gas/mips/org-10.s: New test source. * testsuite/gas/mips/org-11.s: New test source. * testsuite/gas/mips/org-12.s: New test source. * testsuite/gas/mips/mips.exp: Run the new tests.
-rw-r--r--gas/ChangeLog53
-rw-r--r--gas/testsuite/gas/all/gas.exp28
-rw-r--r--gas/testsuite/gas/all/org-1.d3
-rw-r--r--gas/testsuite/gas/all/org-1.l2
-rw-r--r--gas/testsuite/gas/all/org-1.s25
-rw-r--r--gas/testsuite/gas/all/org-2.d2
-rw-r--r--gas/testsuite/gas/all/org-2.l2
-rw-r--r--gas/testsuite/gas/all/org-2.s9
-rw-r--r--gas/testsuite/gas/all/org-3.d2
-rw-r--r--gas/testsuite/gas/all/org-3.l2
-rw-r--r--gas/testsuite/gas/all/org-3.s9
-rw-r--r--gas/testsuite/gas/all/org-4.d5
-rw-r--r--gas/testsuite/gas/all/org-4.s9
-rw-r--r--gas/testsuite/gas/all/org-5.d5
-rw-r--r--gas/testsuite/gas/all/org-5.s9
-rw-r--r--gas/testsuite/gas/all/org-6.d5
-rw-r--r--gas/testsuite/gas/all/org-6.s9
-rw-r--r--gas/testsuite/gas/mips/mips.exp13
-rw-r--r--gas/testsuite/gas/mips/org-1.d7
-rw-r--r--gas/testsuite/gas/mips/org-1.l2
-rw-r--r--gas/testsuite/gas/mips/org-1.s9
-rw-r--r--gas/testsuite/gas/mips/org-10.d7
-rw-r--r--gas/testsuite/gas/mips/org-10.l2
-rw-r--r--gas/testsuite/gas/mips/org-10.s11
-rw-r--r--gas/testsuite/gas/mips/org-11.d6
-rw-r--r--gas/testsuite/gas/mips/org-11.s13
-rw-r--r--gas/testsuite/gas/mips/org-12.d5
-rw-r--r--gas/testsuite/gas/mips/org-12.s13
-rw-r--r--gas/testsuite/gas/mips/org-2.d6
-rw-r--r--gas/testsuite/gas/mips/org-2.s11
-rw-r--r--gas/testsuite/gas/mips/org-3.d5
-rw-r--r--gas/testsuite/gas/mips/org-3.s11
-rw-r--r--gas/testsuite/gas/mips/org-4.d3
-rw-r--r--gas/testsuite/gas/mips/org-4.l3
-rw-r--r--gas/testsuite/gas/mips/org-4.s11
-rw-r--r--gas/testsuite/gas/mips/org-5.d3
-rw-r--r--gas/testsuite/gas/mips/org-5.l2
-rw-r--r--gas/testsuite/gas/mips/org-5.s13
-rw-r--r--gas/testsuite/gas/mips/org-6.d2
-rw-r--r--gas/testsuite/gas/mips/org-6.l2
-rw-r--r--gas/testsuite/gas/mips/org-6.s13
-rw-r--r--gas/testsuite/gas/mips/org-7.d6
-rw-r--r--gas/testsuite/gas/mips/org-7.s11
-rw-r--r--gas/testsuite/gas/mips/org-8.d6
-rw-r--r--gas/testsuite/gas/mips/org-8.s13
-rw-r--r--gas/testsuite/gas/mips/org-9.d5
-rw-r--r--gas/testsuite/gas/mips/org-9.s13
-rw-r--r--gas/write.c9
48 files changed, 411 insertions, 4 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog
index 9be9530d05..785f9a4965 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -1,3 +1,56 @@
+2017-03-02 Maciej W. Rozycki <macro@imgtec.com>
+
+ * write.c (relax_segment) <rs_org>: Only bail out if the fixed
+ part of the frag has overrun the location requested.
+
+ * testsuite/gas/all/org-1.d: New test.
+ * testsuite/gas/all/org-2.d: New test.
+ * testsuite/gas/all/org-3.d: New test.
+ * testsuite/gas/all/org-4.d: New test.
+ * testsuite/gas/all/org-5.d: New test.
+ * testsuite/gas/all/org-6.d: New test.
+ * testsuite/gas/all/org-1.l: New stderr output.
+ * testsuite/gas/all/org-2.l: New stderr output.
+ * testsuite/gas/all/org-3.l: New stderr output.
+ * testsuite/gas/all/org-1.s: New test source.
+ * testsuite/gas/all/org-2.s: New test source.
+ * testsuite/gas/all/org-3.s: New test source.
+ * testsuite/gas/all/org-4.s: New test source.
+ * testsuite/gas/all/org-5.s: New test source.
+ * testsuite/gas/all/org-6.s: New test source.
+ * testsuite/gas/all/gas.exp: Run the new tests.
+
+ * testsuite/gas/mips/org-1.d: New test.
+ * testsuite/gas/mips/org-2.d: New test.
+ * testsuite/gas/mips/org-3.d: New test.
+ * testsuite/gas/mips/org-4.d: New test.
+ * testsuite/gas/mips/org-5.d: New test.
+ * testsuite/gas/mips/org-6.d: New test.
+ * testsuite/gas/mips/org-7.d: New test.
+ * testsuite/gas/mips/org-8.d: New test.
+ * testsuite/gas/mips/org-9.d: New test.
+ * testsuite/gas/mips/org-10.d: New test.
+ * testsuite/gas/mips/org-11.d: New test.
+ * testsuite/gas/mips/org-12.d: New test.
+ * testsuite/gas/mips/org-1.l: New stderr output.
+ * testsuite/gas/mips/org-4.l: New stderr output.
+ * testsuite/gas/mips/org-5.l: New stderr output.
+ * testsuite/gas/mips/org-6.l: New stderr output.
+ * testsuite/gas/mips/org-10.l: New stderr output.
+ * testsuite/gas/mips/org-1.s: New test source.
+ * testsuite/gas/mips/org-2.s: New test source.
+ * testsuite/gas/mips/org-3.s: New test source.
+ * testsuite/gas/mips/org-4.s: New test source.
+ * testsuite/gas/mips/org-5.s: New test source.
+ * testsuite/gas/mips/org-6.s: New test source.
+ * testsuite/gas/mips/org-7.s: New test source.
+ * testsuite/gas/mips/org-8.s: New test source.
+ * testsuite/gas/mips/org-9.s: New test source.
+ * testsuite/gas/mips/org-10.s: New test source.
+ * testsuite/gas/mips/org-11.s: New test source.
+ * testsuite/gas/mips/org-12.s: New test source.
+ * testsuite/gas/mips/mips.exp: Run the new tests.
+
2017-03-01 Szabolcs Nagy <szabolcs.nagy@arm.com>
* doc/c-aarch64.texi (AArch64 Extensions): Document rcpc.
diff --git a/gas/testsuite/gas/all/gas.exp b/gas/testsuite/gas/all/gas.exp
index 009e68c220..b5b0bebbf3 100644
--- a/gas/testsuite/gas/all/gas.exp
+++ b/gas/testsuite/gas/all/gas.exp
@@ -455,3 +455,31 @@ load_lib gas-dg.exp
dg-init
dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/err-*.s $srcdir/$subdir/warn-*.s]] "" ""
dg-finish
+
+# Set $nop_type appropriately to indicate the NOP instruction mnemonic.
+case $target_triplet in {
+ { "mmix-*-*" } {
+ set nop_type 5
+ }
+ { "i960-*-*" } {
+ set nop_type 4
+ }
+ { "i370-*-*" } {
+ set nop_type 3
+ }
+ { "or1k*-*-*" } {
+ set nop_type 2
+ }
+ { "ia64-*-*" } {
+ set nop_type 1
+ }
+ default {
+ set nop_type 0
+ }
+}
+run_dump_test "org-1" [list [list as "--defsym nop_type=$nop_type"]]
+run_dump_test "org-2"
+run_dump_test "org-3"
+run_dump_test "org-4"
+run_dump_test "org-5"
+run_dump_test "org-6"
diff --git a/gas/testsuite/gas/all/org-1.d b/gas/testsuite/gas/all/org-1.d
new file mode 100644
index 0000000000..983e6d6dae
--- /dev/null
+++ b/gas/testsuite/gas/all/org-1.d
@@ -0,0 +1,3 @@
+#name: .org test 1
+#as: -gdwarf2
+#error-output: org-1.l
diff --git a/gas/testsuite/gas/all/org-1.l b/gas/testsuite/gas/all/org-1.l
new file mode 100644
index 0000000000..79932c0c91
--- /dev/null
+++ b/gas/testsuite/gas/all/org-1.l
@@ -0,0 +1,2 @@
+.*: Assembler messages:
+.*:22: Error: attempt to move \.org backwards
diff --git a/gas/testsuite/gas/all/org-1.s b/gas/testsuite/gas/all/org-1.s
new file mode 100644
index 0000000000..4d7b12bff8
--- /dev/null
+++ b/gas/testsuite/gas/all/org-1.s
@@ -0,0 +1,25 @@
+ .macro i_nop
+ .if nop_type == 1
+ nop 0
+ .elseif nop_type == 2
+ l.nop
+ .elseif nop_type == 3
+ nopr 1
+ .elseif nop_type == 4
+ mov g0, g0
+ .elseif nop_type == 5
+ set $0, $0
+ .else
+ nop
+ .endif
+ .endm
+
+ .text
+ .org 0x20
+ .globl foo
+foo:
+ i_nop
+ .org 0x10
+ .globl bar
+bar:
+ i_nop
diff --git a/gas/testsuite/gas/all/org-2.d b/gas/testsuite/gas/all/org-2.d
new file mode 100644
index 0000000000..6295a970d5
--- /dev/null
+++ b/gas/testsuite/gas/all/org-2.d
@@ -0,0 +1,2 @@
+#name: .org test 2
+#error-output: org-2.l
diff --git a/gas/testsuite/gas/all/org-2.l b/gas/testsuite/gas/all/org-2.l
new file mode 100644
index 0000000000..2995bb06ad
--- /dev/null
+++ b/gas/testsuite/gas/all/org-2.l
@@ -0,0 +1,2 @@
+.*: Assembler messages:
+.*:6: Error: attempt to move \.org backwards
diff --git a/gas/testsuite/gas/all/org-2.s b/gas/testsuite/gas/all/org-2.s
new file mode 100644
index 0000000000..4eb0d1fbce
--- /dev/null
+++ b/gas/testsuite/gas/all/org-2.s
@@ -0,0 +1,9 @@
+ .data
+ .org 0x10
+ .globl foo
+foo:
+ .byte 0, 1, 2, 3
+ .org 0x10
+ .globl bar
+bar:
+ .byte 0, 1, 2, 3
diff --git a/gas/testsuite/gas/all/org-3.d b/gas/testsuite/gas/all/org-3.d
new file mode 100644
index 0000000000..d719403ac3
--- /dev/null
+++ b/gas/testsuite/gas/all/org-3.d
@@ -0,0 +1,2 @@
+#name: .org test 3
+#error-output: org-3.l
diff --git a/gas/testsuite/gas/all/org-3.l b/gas/testsuite/gas/all/org-3.l
new file mode 100644
index 0000000000..2995bb06ad
--- /dev/null
+++ b/gas/testsuite/gas/all/org-3.l
@@ -0,0 +1,2 @@
+.*: Assembler messages:
+.*:6: Error: attempt to move \.org backwards
diff --git a/gas/testsuite/gas/all/org-3.s b/gas/testsuite/gas/all/org-3.s
new file mode 100644
index 0000000000..3ec47edd00
--- /dev/null
+++ b/gas/testsuite/gas/all/org-3.s
@@ -0,0 +1,9 @@
+ .data
+ .org 0x10
+ .globl foo
+foo:
+ .byte 0, 1, 2, 3
+ .org 0x13
+ .globl bar
+bar:
+ .byte 0, 1, 2, 3
diff --git a/gas/testsuite/gas/all/org-4.d b/gas/testsuite/gas/all/org-4.d
new file mode 100644
index 0000000000..57b1e7fec0
--- /dev/null
+++ b/gas/testsuite/gas/all/org-4.d
@@ -0,0 +1,5 @@
+#nm: -g --defined-only
+#name: .org test 4
+
+0+000014 . bar
+0+000010 . foo
diff --git a/gas/testsuite/gas/all/org-4.s b/gas/testsuite/gas/all/org-4.s
new file mode 100644
index 0000000000..6f43492237
--- /dev/null
+++ b/gas/testsuite/gas/all/org-4.s
@@ -0,0 +1,9 @@
+ .data
+ .org 0x10
+ .globl foo
+foo:
+ .byte 0, 1, 2, 3
+ .org 0x14
+ .globl bar
+bar:
+ .byte 0, 1, 2, 3
diff --git a/gas/testsuite/gas/all/org-5.d b/gas/testsuite/gas/all/org-5.d
new file mode 100644
index 0000000000..45f72f36c9
--- /dev/null
+++ b/gas/testsuite/gas/all/org-5.d
@@ -0,0 +1,5 @@
+#nm: -g --defined-only
+#name: .org test 5
+
+0+000015 . bar
+0+000010 . foo
diff --git a/gas/testsuite/gas/all/org-5.s b/gas/testsuite/gas/all/org-5.s
new file mode 100644
index 0000000000..cf075aab24
--- /dev/null
+++ b/gas/testsuite/gas/all/org-5.s
@@ -0,0 +1,9 @@
+ .data
+ .org 0x10
+ .globl foo
+foo:
+ .byte 0, 1, 2, 3
+ .org 0x15
+ .globl bar
+bar:
+ .byte 0, 1, 2, 3
diff --git a/gas/testsuite/gas/all/org-6.d b/gas/testsuite/gas/all/org-6.d
new file mode 100644
index 0000000000..25fed71183
--- /dev/null
+++ b/gas/testsuite/gas/all/org-6.d
@@ -0,0 +1,5 @@
+#nm: -g --defined-only
+#name: .org test 6
+
+0+000018 . bar
+0+000010 . foo
diff --git a/gas/testsuite/gas/all/org-6.s b/gas/testsuite/gas/all/org-6.s
new file mode 100644
index 0000000000..19ad016e5d
--- /dev/null
+++ b/gas/testsuite/gas/all/org-6.s
@@ -0,0 +1,9 @@
+ .data
+ .org 0x10
+ .globl foo
+foo:
+ .byte 0, 1, 2, 3
+ .org 0x18
+ .globl bar
+bar:
+ .byte 0, 1, 2, 3
diff --git a/gas/testsuite/gas/mips/mips.exp b/gas/testsuite/gas/mips/mips.exp
index 591af507a2..f0c6c34dcd 100644
--- a/gas/testsuite/gas/mips/mips.exp
+++ b/gas/testsuite/gas/mips/mips.exp
@@ -1806,6 +1806,19 @@ if { [istarget mips*-*-vxworks*] } {
run_dump_test "debug-label-end-2"
run_dump_test "debug-label-end-3"
+ run_dump_test "org-1"
+ run_dump_test "org-2"
+ run_dump_test "org-3"
+ run_dump_test "org-4"
+ run_dump_test "org-5"
+ run_dump_test "org-6"
+ run_dump_test "org-7"
+ run_dump_test "org-8"
+ run_dump_test "org-9"
+ run_dump_test "org-10"
+ run_dump_test "org-11"
+ run_dump_test "org-12"
+
run_dump_test_arches "r6" [mips_arch_list_matching mips32r6]
if $has_newabi {
run_dump_test_arches "r6-n32" [mips_arch_list_matching mips64r6]
diff --git a/gas/testsuite/gas/mips/org-1.d b/gas/testsuite/gas/mips/org-1.d
new file mode 100644
index 0000000000..824d6fff0c
--- /dev/null
+++ b/gas/testsuite/gas/mips/org-1.d
@@ -0,0 +1,7 @@
+#nm: -g --defined-only
+#as: --relax-branch
+#name: MIPS .org test 1
+#stderr: org-1.l
+
+0+100000 . bar
+0+000000 . foo
diff --git a/gas/testsuite/gas/mips/org-1.l b/gas/testsuite/gas/mips/org-1.l
new file mode 100644
index 0000000000..4dade8115e
--- /dev/null
+++ b/gas/testsuite/gas/mips/org-1.l
@@ -0,0 +1,2 @@
+.*: Assembler messages:
+.*:4: Warning: relaxed out-of-range branch into a jump
diff --git a/gas/testsuite/gas/mips/org-1.s b/gas/testsuite/gas/mips/org-1.s
new file mode 100644
index 0000000000..95177c349c
--- /dev/null
+++ b/gas/testsuite/gas/mips/org-1.s
@@ -0,0 +1,9 @@
+ .text
+ .globl foo
+foo:
+ beqz $2, lbar
+ .org 0x100000
+ .globl bar
+bar:
+lbar:
+ nop
diff --git a/gas/testsuite/gas/mips/org-10.d b/gas/testsuite/gas/mips/org-10.d
new file mode 100644
index 0000000000..520e779810
--- /dev/null
+++ b/gas/testsuite/gas/mips/org-10.d
@@ -0,0 +1,7 @@
+#nm: -g --defined-only
+#as: --relax-branch
+#name: MIPS .org test 10
+#stderr: org-10.l
+
+0+100000 . bar
+0+000000 . foo
diff --git a/gas/testsuite/gas/mips/org-10.l b/gas/testsuite/gas/mips/org-10.l
new file mode 100644
index 0000000000..4dade8115e
--- /dev/null
+++ b/gas/testsuite/gas/mips/org-10.l
@@ -0,0 +1,2 @@
+.*: Assembler messages:
+.*:4: Warning: relaxed out-of-range branch into a jump
diff --git a/gas/testsuite/gas/mips/org-10.s b/gas/testsuite/gas/mips/org-10.s
new file mode 100644
index 0000000000..74a7d0c97f
--- /dev/null
+++ b/gas/testsuite/gas/mips/org-10.s
@@ -0,0 +1,11 @@
+ .text
+ .globl foo
+foo:
+ beqz $2, lbar
+ .org 0x10
+ nop
+ .space 0xfffec
+ .globl bar
+bar:
+lbar:
+ nop
diff --git a/gas/testsuite/gas/mips/org-11.d b/gas/testsuite/gas/mips/org-11.d
new file mode 100644
index 0000000000..b464230cd7
--- /dev/null
+++ b/gas/testsuite/gas/mips/org-11.d
@@ -0,0 +1,6 @@
+#nm: -g --defined-only
+#as: -32
+#name: MIPS .org test 11
+
+0+001000 . bar
+0+000000 . foo
diff --git a/gas/testsuite/gas/mips/org-11.s b/gas/testsuite/gas/mips/org-11.s
new file mode 100644
index 0000000000..61eefb2241
--- /dev/null
+++ b/gas/testsuite/gas/mips/org-11.s
@@ -0,0 +1,13 @@
+ .set mips16
+ .text
+ .globl foo
+foo:
+ la $2, lbar
+ .org 0x4
+ nop
+ .space 0xffa
+ .align 2
+ .globl bar
+bar = .
+lbar = .
+ nop
diff --git a/gas/testsuite/gas/mips/org-12.d b/gas/testsuite/gas/mips/org-12.d
new file mode 100644
index 0000000000..323c301045
--- /dev/null
+++ b/gas/testsuite/gas/mips/org-12.d
@@ -0,0 +1,5 @@
+#nm: -g --defined-only
+#name: MIPS .org test 12
+
+0+001000 . bar
+0+000000 . foo
diff --git a/gas/testsuite/gas/mips/org-12.s b/gas/testsuite/gas/mips/org-12.s
new file mode 100644
index 0000000000..5a01440a88
--- /dev/null
+++ b/gas/testsuite/gas/mips/org-12.s
@@ -0,0 +1,13 @@
+ .set micromips
+ .text
+ .globl foo
+foo:
+ addu $4, $3, $2
+ beqz $2, lbar
+ .org 0x6
+ nop
+ .space 0xff8
+ .globl bar
+bar:
+lbar:
+ nop
diff --git a/gas/testsuite/gas/mips/org-2.d b/gas/testsuite/gas/mips/org-2.d
new file mode 100644
index 0000000000..abdd5638a0
--- /dev/null
+++ b/gas/testsuite/gas/mips/org-2.d
@@ -0,0 +1,6 @@
+#nm: -g --defined-only
+#as: -32
+#name: MIPS .org test 2
+
+0+001000 . bar
+0+000000 . foo
diff --git a/gas/testsuite/gas/mips/org-2.s b/gas/testsuite/gas/mips/org-2.s
new file mode 100644
index 0000000000..6cb07bd22d
--- /dev/null
+++ b/gas/testsuite/gas/mips/org-2.s
@@ -0,0 +1,11 @@
+ .set mips16
+ .text
+ .globl foo
+foo:
+ la $2, lbar
+ .org 0x1000
+ .align 2
+ .globl bar
+bar = .
+lbar = .
+ nop
diff --git a/gas/testsuite/gas/mips/org-3.d b/gas/testsuite/gas/mips/org-3.d
new file mode 100644
index 0000000000..04d520874d
--- /dev/null
+++ b/gas/testsuite/gas/mips/org-3.d
@@ -0,0 +1,5 @@
+#nm: -g --defined-only
+#name: MIPS .org test 3
+
+0+001000 . bar
+0+000000 . foo
diff --git a/gas/testsuite/gas/mips/org-3.s b/gas/testsuite/gas/mips/org-3.s
new file mode 100644
index 0000000000..d3c6eb4fc3
--- /dev/null
+++ b/gas/testsuite/gas/mips/org-3.s
@@ -0,0 +1,11 @@
+ .set micromips
+ .text
+ .globl foo
+foo:
+ addu $4, $3, $2
+ beqz $2, lbar
+ .org 0x1000
+ .globl bar
+bar:
+lbar:
+ nop
diff --git a/gas/testsuite/gas/mips/org-4.d b/gas/testsuite/gas/mips/org-4.d
new file mode 100644
index 0000000000..9d6af7ac15
--- /dev/null
+++ b/gas/testsuite/gas/mips/org-4.d
@@ -0,0 +1,3 @@
+#as: --relax-branch
+#name: MIPS .org test 4
+#error-output: org-4.l
diff --git a/gas/testsuite/gas/mips/org-4.l b/gas/testsuite/gas/mips/org-4.l
new file mode 100644
index 0000000000..138515cfec
--- /dev/null
+++ b/gas/testsuite/gas/mips/org-4.l
@@ -0,0 +1,3 @@
+.*: Assembler messages:
+.*:5: Error: attempt to move \.org backwards
+.*:4: Warning: relaxed out-of-range branch into a jump
diff --git a/gas/testsuite/gas/mips/org-4.s b/gas/testsuite/gas/mips/org-4.s
new file mode 100644
index 0000000000..c81fde9af4
--- /dev/null
+++ b/gas/testsuite/gas/mips/org-4.s
@@ -0,0 +1,11 @@
+ .text
+ .globl foo
+foo:
+ beqz $2, lbar
+ .org 0xc
+ nop
+ .space 0xffff0
+ .globl bar
+bar:
+lbar:
+ nop
diff --git a/gas/testsuite/gas/mips/org-5.d b/gas/testsuite/gas/mips/org-5.d
new file mode 100644
index 0000000000..b8dca13655
--- /dev/null
+++ b/gas/testsuite/gas/mips/org-5.d
@@ -0,0 +1,3 @@
+#as: -32
+#name: MIPS .org test 5
+#error-output: org-5.l
diff --git a/gas/testsuite/gas/mips/org-5.l b/gas/testsuite/gas/mips/org-5.l
new file mode 100644
index 0000000000..2995bb06ad
--- /dev/null
+++ b/gas/testsuite/gas/mips/org-5.l
@@ -0,0 +1,2 @@
+.*: Assembler messages:
+.*:6: Error: attempt to move \.org backwards
diff --git a/gas/testsuite/gas/mips/org-5.s b/gas/testsuite/gas/mips/org-5.s
new file mode 100644
index 0000000000..ae426b2e30
--- /dev/null
+++ b/gas/testsuite/gas/mips/org-5.s
@@ -0,0 +1,13 @@
+ .set mips16
+ .text
+ .globl foo
+foo:
+ la $2, lbar
+ .org 0x2
+ nop
+ .space 0xffc
+ .align 2
+ .globl bar
+bar = .
+lbar = .
+ nop
diff --git a/gas/testsuite/gas/mips/org-6.d b/gas/testsuite/gas/mips/org-6.d
new file mode 100644
index 0000000000..9bc6ce7ee5
--- /dev/null
+++ b/gas/testsuite/gas/mips/org-6.d
@@ -0,0 +1,2 @@
+#name: MIPS .org test 6
+#error-output: org-6.l
diff --git a/gas/testsuite/gas/mips/org-6.l b/gas/testsuite/gas/mips/org-6.l
new file mode 100644
index 0000000000..d8ccddb949
--- /dev/null
+++ b/gas/testsuite/gas/mips/org-6.l
@@ -0,0 +1,2 @@
+.*: Assembler messages:
+.*:7: Error: attempt to move \.org backwards
diff --git a/gas/testsuite/gas/mips/org-6.s b/gas/testsuite/gas/mips/org-6.s
new file mode 100644
index 0000000000..bbc42b89b2
--- /dev/null
+++ b/gas/testsuite/gas/mips/org-6.s
@@ -0,0 +1,13 @@
+ .set micromips
+ .text
+ .globl foo
+foo:
+ addu $4, $3, $2
+ beqz $2, lbar
+ .org 0x4
+ nop
+ .space 0xffa
+ .globl bar
+bar:
+lbar:
+ nop
diff --git a/gas/testsuite/gas/mips/org-7.d b/gas/testsuite/gas/mips/org-7.d
new file mode 100644
index 0000000000..71f545db14
--- /dev/null
+++ b/gas/testsuite/gas/mips/org-7.d
@@ -0,0 +1,6 @@
+#nm: -g --defined-only
+#as: --relax-branch
+#name: MIPS .org test 7
+
+0+010000 . bar
+0+000000 . foo
diff --git a/gas/testsuite/gas/mips/org-7.s b/gas/testsuite/gas/mips/org-7.s
new file mode 100644
index 0000000000..b0a88bd3c1
--- /dev/null
+++ b/gas/testsuite/gas/mips/org-7.s
@@ -0,0 +1,11 @@
+ .text
+ .globl foo
+foo:
+ beqz $2, lbar
+ .org 0x8
+ nop
+ .space 0xfff4
+ .globl bar
+bar:
+lbar:
+ nop
diff --git a/gas/testsuite/gas/mips/org-8.d b/gas/testsuite/gas/mips/org-8.d
new file mode 100644
index 0000000000..0d1acf934e
--- /dev/null
+++ b/gas/testsuite/gas/mips/org-8.d
@@ -0,0 +1,6 @@
+#nm: -g --defined-only
+#as: -32
+#name: MIPS .org test 8
+
+0+000100 . bar
+0+000000 . foo
diff --git a/gas/testsuite/gas/mips/org-8.s b/gas/testsuite/gas/mips/org-8.s
new file mode 100644
index 0000000000..097163ce86
--- /dev/null
+++ b/gas/testsuite/gas/mips/org-8.s
@@ -0,0 +1,13 @@
+ .set mips16
+ .text
+ .globl foo
+foo:
+ la $2, lbar
+ .org 0x2
+ nop
+ .space 0xfc
+ .align 2
+ .globl bar
+bar = .
+lbar = .
+ nop
diff --git a/gas/testsuite/gas/mips/org-9.d b/gas/testsuite/gas/mips/org-9.d
new file mode 100644
index 0000000000..fe9e3f313c
--- /dev/null
+++ b/gas/testsuite/gas/mips/org-9.d
@@ -0,0 +1,5 @@
+#nm: -g --defined-only
+#name: MIPS .org test 9
+
+0+000080 . bar
+0+000000 . foo
diff --git a/gas/testsuite/gas/mips/org-9.s b/gas/testsuite/gas/mips/org-9.s
new file mode 100644
index 0000000000..90405b39fd
--- /dev/null
+++ b/gas/testsuite/gas/mips/org-9.s
@@ -0,0 +1,13 @@
+ .set micromips
+ .text
+ .globl foo
+foo:
+ addu $4, $3, $2
+ beqz $2, lbar
+ .org 0x4
+ nop
+ .space 0x7a
+ .globl bar
+bar:
+lbar:
+ nop
diff --git a/gas/write.c b/gas/write.c
index 9a99a0f5ae..d570b6f5ba 100644
--- a/gas/write.c
+++ b/gas/write.c
@@ -2692,7 +2692,11 @@ relax_segment (struct frag *segment_frag_root, segT segment, int pass)
know (fragP->fr_next);
after = fragP->fr_next->fr_address + stretch;
growth = target - after;
- if (growth < 0)
+
+ /* Growth may be negative, but variable part of frag
+ cannot have fewer than 0 chars. That is, we can't
+ .org backwards. */
+ if (address + fragP->fr_fix > target)
{
growth = 0;
@@ -2714,9 +2718,6 @@ relax_segment (struct frag *segment_frag_root, segT segment, int pass)
break;
}
- /* Growth may be negative, but variable part of frag
- cannot have fewer than 0 chars. That is, we can't
- .org backwards. */
as_bad_where (fragP->fr_file, fragP->fr_line,
_("attempt to move .org backwards"));