+2008-09-19  Alan Modra  <amodra@bigpond.net.au>
+
+       * write.c (md_register_arithmetic): Define.
+       (fixup_segment): Adjust TC_FORCE_RELOCATION_SUB_ABS invocation.
+       Modify error message when registers involved.
+       (TC_FORCE_RELOCATION_SUB_ABS): Heed md_register_arithmetic.
+       * config/tc-sh.h (TC_FORCE_RELOCATION_SUB_ABS): Likewise.
+
 2008-09-15  Alan Modra  <amodra@bigpond.net.au>
 
        * write.c (install_reloc): Correct EMIT_SECTION_SYMBOLS test.
 
 
 /* This keeps the subtracted symbol around, for use by PLT_PCREL
    relocs.  */
-#define TC_FORCE_RELOCATION_SUB_ABS(FIX)               \
-  ((FIX)->fx_r_type == BFD_RELOC_32_PLT_PCREL)
+#define TC_FORCE_RELOCATION_SUB_ABS(FIX, SEG)          \
+  ((FIX)->fx_r_type == BFD_RELOC_32_PLT_PCREL          \
+   || (!md_register_arithmetic && (SEG) == reg_section))
 
 /* Don't complain when we leave fx_subsy around.  */
 #undef TC_VALIDATE_FIX_SUB
 
   (! SEG_NORMAL (SEG))
 #endif
 
+#ifndef md_register_arithmetic
+# define md_register_arithmetic 1
+#endif
+
 #ifndef TC_FORCE_RELOCATION_SUB_ABS
-#define TC_FORCE_RELOCATION_SUB_ABS(FIX)       0
+#define TC_FORCE_RELOCATION_SUB_ABS(FIX, SEG)  \
+  (!md_register_arithmetic && (SEG) == reg_section)
 #endif
 
 #ifndef TC_FORCE_RELOCATION_SUB_LOCAL
 #endif
            }
          else if (sub_symbol_segment == absolute_section
-                  && !TC_FORCE_RELOCATION_SUB_ABS (fixP))
+                  && !TC_FORCE_RELOCATION_SUB_ABS (fixP, add_symbol_segment))
            {
              add_number -= S_GET_VALUE (fixP->fx_subsy);
              fixP->fx_offset = add_number;
            }
          else if (!TC_VALIDATE_FIX_SUB (fixP))
            {
-             as_bad_where (fixP->fx_file, fixP->fx_line,
-                           _("can't resolve `%s' {%s section} - `%s' {%s section}"),
-                           fixP->fx_addsy ? S_GET_NAME (fixP->fx_addsy) : "0",
-                           segment_name (add_symbol_segment),
-                           S_GET_NAME (fixP->fx_subsy),
-                           segment_name (sub_symbol_segment));
+             if (!md_register_arithmetic
+                 && (add_symbol_segment == reg_section
+                     || sub_symbol_segment == reg_section))
+               as_bad_where (fixP->fx_file, fixP->fx_line,
+                             _("register value used as expression"));
+             else
+               as_bad_where (fixP->fx_file, fixP->fx_line,
+                             _("can't resolve `%s' {%s section} - `%s' {%s section}"),
+                             fixP->fx_addsy ? S_GET_NAME (fixP->fx_addsy) : "0",
+                             segment_name (add_symbol_segment),
+                             S_GET_NAME (fixP->fx_subsy),
+                             segment_name (sub_symbol_segment));
            }
        }