* read.c (read_a_source_file): If NO_PSEUDO_DOT is defined, look
[binutils-gdb.git] / gas / config / obj-coffbfd.c
index c8b70603fc70eed60fbf076407295b61abc3a9e2..9a0a460a5139d5e4b194b997702bedd5bdb0a993 100644 (file)
@@ -1,5 +1,5 @@
 /* coff object file format with bfd
-   Copyright (C) 1989, 1990, 1991 Free Software Foundation, Inc.
+   Copyright (C) 1989, 1990, 1991, 1993 Free Software Foundation, Inc.
 
 This file is part of GAS.
 
@@ -68,11 +68,8 @@ const short seg_N_TYPE[] =
   9,
   10,
   C_UNDEF_SECTION,             /* SEG_UNKNOWN */
-  C_UNDEF_SECTION,             /* SEG_ABSENT */
-  C_UNDEF_SECTION,             /* SEG_PASS1 */
   C_UNDEF_SECTION,             /* SEG_GOOF */
-  C_UNDEF_SECTION,             /* SEG_BIG */
-  C_UNDEF_SECTION,             /* SEG_DIFFERENCE */
+  C_UNDEF_SECTION,             /* SEG_EXPR */
   C_DEBUG_SECTION,             /* SEG_DEBUG */
   C_NTV_SECTION,               /* SEG_NTV */
   C_PTV_SECTION,               /* SEG_PTV */
@@ -142,7 +139,7 @@ static void EXFUN( obj_coff_bss,(void));
 static void EXFUN( obj_coff_ident,(void));
 static void EXFUN (obj_coff_endef, (void));
 static void EXFUN (obj_coff_line, (void));
-static void EXFUN (obj_coff_ln, (void));
+static void EXFUN (obj_coff_ln, (int));
 static void EXFUN (obj_coff_scl, (void));
 static void EXFUN (obj_coff_size, (void));
 static void EXFUN (obj_coff_tag, (void));
@@ -163,6 +160,7 @@ const pseudo_typeS obj_pseudo_table[] =
   {"endef", obj_coff_endef, 0},
   {"line", obj_coff_line, 0},
   {"ln", obj_coff_ln, 0},
+  {"appline", obj_coff_ln, 1},
   {"scl", obj_coff_scl, 0},
   {"size", obj_coff_size, 0},
   {"tag", obj_coff_tag, 0},
@@ -177,6 +175,10 @@ const pseudo_typeS obj_pseudo_table[] =
   {"ident", obj_coff_ident, 0},
   {"ABORT", s_abort, 0},
   {"lcomm", obj_coff_lcomm, 0},
+#ifdef TC_M88K
+  /* The m88k uses sdef instead of def.  */
+  {"sdef", obj_coff_def, 0},
+#endif
   {NULL}                       /* end sentinel */
 };                             /* obj_pseudo_table */
 
@@ -359,100 +361,106 @@ DEFUN (do_relocs_for, (abfd, h, file_cursor),
          struct external_reloc *ext_ptr;
          struct external_reloc *external_reloc_vec;
          unsigned int external_reloc_size;
-         unsigned int count = 0;
          unsigned int base = segment_info[idx].scnhdr.s_paddr;
          fixS *fix_ptr = segment_info[idx].fix_root;
          nrelocs = count_entries_in_chain (idx);
 
-         external_reloc_size = nrelocs * RELSZ;
-         external_reloc_vec =
-           (struct external_reloc *) malloc (external_reloc_size);
-
-         ext_ptr = external_reloc_vec;
-
-         /* Fill in the internal coff style reloc struct from the
-            internal fix list.  */
-         while (fix_ptr)
+         if (nrelocs)
+           /* Bypass this stuff if no relocs.  This also incidentally
+              avoids a SCO bug, where free(malloc(0)) tends to crash.  */
            {
-             symbolS *symbol_ptr;
-             struct internal_reloc intr;
+             external_reloc_size = nrelocs * RELSZ;
+             external_reloc_vec =
+               (struct external_reloc *) malloc (external_reloc_size);
 
-             /* Only output some of the relocations */
-             if (TC_COUNT_RELOC (fix_ptr))
+             ext_ptr = external_reloc_vec;
+
+             /* Fill in the internal coff style reloc struct from the
+                internal fix list.  */
+             while (fix_ptr)
                {
+                 symbolS *symbol_ptr;
+                 struct internal_reloc intr;
+
+                 /* Only output some of the relocations */
+                 if (TC_COUNT_RELOC (fix_ptr))
+                   {
 #ifdef TC_RELOC_MANGLE
-                 TC_RELOC_MANGLE (fix_ptr, &intr, base);
+                     TC_RELOC_MANGLE (fix_ptr, &intr, base);
 
 #else
-                 symbolS *dot;
-                 symbol_ptr = fix_ptr->fx_addsy;
-
-                 intr.r_type = TC_COFF_FIX2RTYPE (fix_ptr);
-                 intr.r_vaddr =
-                   base + fix_ptr->fx_frag->fr_address + fix_ptr->fx_where;
+                     symbolS *dot;
+                     symbol_ptr = fix_ptr->fx_addsy;
 
-                 intr.r_offset = fix_ptr->fx_offset;
+                     intr.r_type = TC_COFF_FIX2RTYPE (fix_ptr);
+                     intr.r_vaddr =
+                       base + fix_ptr->fx_frag->fr_address + fix_ptr->fx_where;
 
-                 intr.r_offset = 0;
+#ifdef TC_M88K
+                     intr.r_offset = fix_ptr->fx_offset;
+#else
+                     intr.r_offset = 0;
+#endif
 
-                 /* Turn the segment of the symbol into an offset.  */
-                 if (symbol_ptr)
-                   {
-                     dot = segment_info[S_GET_SEGMENT (symbol_ptr)].dot;
-                     if (dot)
+                     /* Turn the segment of the symbol into an offset.  */
+                     if (symbol_ptr)
                        {
-                         intr.r_symndx = dot->sy_number;
+                         dot = segment_info[S_GET_SEGMENT (symbol_ptr)].dot;
+                         if (dot)
+                           {
+                             intr.r_symndx = dot->sy_number;
+                           }
+                         else
+                           {
+                             intr.r_symndx = symbol_ptr->sy_number;
+                           }
+
                        }
                      else
                        {
-                         intr.r_symndx = symbol_ptr->sy_number;
+                         intr.r_symndx = -1;
                        }
-
-                   }
-                 else
-                   {
-                     intr.r_symndx = -1;
-                   }
 #endif
 
-                 (void) bfd_coff_swap_reloc_out (abfd, &intr, ext_ptr);
-                 ext_ptr++;
+                     (void) bfd_coff_swap_reloc_out (abfd, &intr, ext_ptr);
+                     ext_ptr++;
 
 #if defined(TC_A29K)
 
-                 /* The 29k has a special kludge for the high 16 bit
-                    reloc.  Two relocations are emited, R_IHIHALF,
-                    and R_IHCONST. The second one doesn't contain a
-                    symbol, but uses the value for offset.  */
+                     /* The 29k has a special kludge for the high 16 bit
+                        reloc.  Two relocations are emited, R_IHIHALF,
+                        and R_IHCONST. The second one doesn't contain a
+                        symbol, but uses the value for offset.  */
 
-                 if (intr.r_type == R_IHIHALF)
-                   {
-                     /* now emit the second bit */
-                     intr.r_type = R_IHCONST;
-                     intr.r_symndx = fix_ptr->fx_addnumber;
-
-                     /* The offset to the segment holding the symbol
-                        has already been counted in the R_IHIHALF.
-                        We don't want to add it in again for the
-                        R_IHCONST.  */
-                     if (symbol_ptr)
-                       intr.r_symndx -=
-                         segment_info[S_GET_SEGMENT (symbol_ptr)].scnhdr.s_paddr;
-                     (void) bfd_coff_swap_reloc_out (abfd, &intr, ext_ptr);
-                     ext_ptr++;
-                   }
+                     if (intr.r_type == R_IHIHALF)
+                       {
+                         /* now emit the second bit */
+                         intr.r_type = R_IHCONST;
+                         intr.r_symndx = fix_ptr->fx_addnumber;
+                         (void) bfd_coff_swap_reloc_out (abfd, &intr, ext_ptr);
+                         ext_ptr++;
+                       }
 #endif
+                   }
+
+                 fix_ptr = fix_ptr->fx_next;
                }
 
-             fix_ptr = fix_ptr->fx_next;
-           }
+             /* Write out the reloc table */
+             bfd_write ((PTR) external_reloc_vec, 1, external_reloc_size,
+                        abfd);
+             free (external_reloc_vec);
 
-         /* Write out the reloc table */
-         segment_info[idx].scnhdr.s_relptr = nrelocs ? *file_cursor : 0;
-         segment_info[idx].scnhdr.s_nreloc = nrelocs;
-         bfd_write ((PTR) external_reloc_vec, 1, external_reloc_size, abfd);
-         *file_cursor += external_reloc_size;
-         free (external_reloc_vec);
+             /* Fill in section header info.  */
+             segment_info[idx].scnhdr.s_relptr = *file_cursor;
+             *file_cursor += external_reloc_size;
+             segment_info[idx].scnhdr.s_nreloc = nrelocs;
+           }
+         else
+           {
+             /* No relocs */
+             segment_info[idx].scnhdr.s_relptr = 0;
+           }
        }
     }
   /* Set relocation_size field in file headers */
@@ -493,7 +501,6 @@ DEFUN (fill_section, (abfd, h, file_cursor),
            }
          know (s->s_paddr == paddr);
 
-         s->s_flags = STYP_REG;
          if (strcmp (s->s_name, ".text") == 0)
            s->s_flags |= STYP_TEXT;
          else if (strcmp (s->s_name, ".data") == 0)
@@ -503,9 +510,11 @@ DEFUN (fill_section, (abfd, h, file_cursor),
              s->s_scnptr = 0;
              s->s_flags |= STYP_BSS;
 #ifndef TC_I386
+#ifndef TC_A29K
              /* Apparently the SVR3 linker is confused by noload
-                sections.  */
+                sections.  So is the UDI mondfe program.  */
              s->s_flags |= STYP_NOLOAD;
+#endif
 #endif
            }
          else if (strcmp (s->s_name, ".lit") == 0)
@@ -544,7 +553,7 @@ DEFUN (fill_section, (abfd, h, file_cursor),
                    }
 
                  fill_size = frag->fr_var;
-                 if (fill_size)
+                 if (fill_size && frag->fr_offset > 0)
                    {
                      unsigned int count;
                      unsigned int off = frag->fr_fix;
@@ -635,6 +644,7 @@ DEFUN (symbol_to_chars, (abfd, where, symbolP),
 {
   unsigned int numaux = symbolP->sy_symbol.ost_entry.n_numaux;
   unsigned int i;
+  valueT val;
 
   /* Turn any symbols with register attributes into abs symbols */
   if (S_GET_SEGMENT (symbolP) == SEG_REGISTER)
@@ -643,9 +653,12 @@ DEFUN (symbol_to_chars, (abfd, where, symbolP),
     }
   /* At the same time, relocate all symbols to their output value */
 
-  S_SET_VALUE (symbolP,
-              segment_info[S_GET_SEGMENT (symbolP)].scnhdr.s_paddr
-              + S_GET_VALUE (symbolP));
+  val = (segment_info[S_GET_SEGMENT (symbolP)].scnhdr.s_paddr
+        + S_GET_VALUE (symbolP));
+
+  S_SET_VALUE (symbolP, val);
+
+  symbolP->sy_symbol.ost_entry.n_value = val;
 
   where += bfd_coff_swap_sym_out (abfd, &symbolP->sy_symbol.ost_entry,
                                  where);
@@ -663,8 +676,6 @@ DEFUN (symbol_to_chars, (abfd, where, symbolP),
 }
 
 
-
-
 void
 obj_symbol_new_hook (symbolP)
      symbolS *symbolP;
@@ -773,11 +784,12 @@ stack_top (st)
  */
 
 static void
-obj_coff_ln ()
+obj_coff_ln (appline)
+     int appline;
 {
   int l;
 
-  if (def_symbol_in_progress != NULL)
+  if (! appline && def_symbol_in_progress != NULL)
     {
       as_warn (".ln pseudo-op inside .def/.endef: ignored.");
       demand_empty_rest_of_line ();
@@ -794,7 +806,9 @@ obj_coff_ln ()
 
     if (listing)
       {
-       listing_source_line (l + line_base - 1);
+       if (! appline)
+         l += line_base - 1;
+       listing_source_line (l);
       }
 
   }
@@ -864,6 +878,7 @@ DEFUN (obj_coff_def, (what),
   def_symbol_in_progress->sy_name_offset = ~0;
   def_symbol_in_progress->sy_number = ~0;
   def_symbol_in_progress->sy_frag = &zero_address_frag;
+  S_SET_VALUE (def_symbol_in_progress, 0);
 
   if (S_IS_STRING (def_symbol_in_progress))
     {
@@ -955,55 +970,47 @@ DEFUN_VOID (obj_coff_endef)
       break;
     }                          /* switch on storage class */
 
-  /* Now that we have built a debug symbol, try to find if
-       we should merge with an existing symbol or not.  If a
-       symbol is C_EFCN or SEG_ABSOLUTE or untagged
-       SEG_DEBUG it never merges.  We also don't merge
-       labels, which are in a different namespace, nor
-       symbols which have not yet been defined since they
-       are typically unique, nor do we merge tags with
-       non-tags.  */
-
-  /* Two cases for functions.  Either debug followed
-       by definition or definition followed by debug.
-       For definition first, we will merge the debug
-       symbol into the definition.  For debug first, the
-       lineno entry MUST point to the definition
-       function or else it will point off into space
-       when crawl_symbols() merges the debug
-       symbol into the real symbol.  Therefor, let's
-       presume the debug symbol is a real function
-       reference. */
-
-  /* FIXME-SOON If for some reason the definition
-       label/symbol is never seen, this will probably
-       leave an undefined symbol at link time. */
+  /* Now that we have built a debug symbol, try to find if we should
+     merge with an existing symbol or not.  If a symbol is C_EFCN or
+     SEG_ABSOLUTE or untagged SEG_DEBUG it never merges.  We also
+     don't merge labels, which are in a different namespace, nor
+     symbols which have not yet been defined since they are typically
+     unique, nor do we merge tags with non-tags.  */
+
+  /* Two cases for functions.  Either debug followed by definition or
+     definition followed by debug.  For definition first, we will
+     merge the debug symbol into the definition.  For debug first, the
+     lineno entry MUST point to the definition function or else it
+     will point off into space when crawl_symbols() merges the debug
+     symbol into the real symbol.  Therefor, let's presume the debug
+     symbol is a real function reference. */
+
+  /* FIXME-SOON If for some reason the definition label/symbol is
+     never seen, this will probably leave an undefined symbol at link
+     time. */
 
   if (S_GET_STORAGE_CLASS (def_symbol_in_progress) == C_EFCN
       || S_GET_STORAGE_CLASS (def_symbol_in_progress) == C_LABEL
       || (S_GET_SEGMENT (def_symbol_in_progress) == SEG_DEBUG
          && !SF_GET_TAG (def_symbol_in_progress))
       || S_GET_SEGMENT (def_symbol_in_progress) == SEG_ABSOLUTE
-      || def_symbol_in_progress->sy_forward != NULL
+      || def_symbol_in_progress->sy_value.X_op != O_constant
       || (symbolP = symbol_find_base (S_GET_NAME (def_symbol_in_progress), DO_NOT_STRIP)) == NULL
       || (SF_GET_TAG (def_symbol_in_progress) != SF_GET_TAG (symbolP)))
     {
-
-      symbol_append (def_symbol_in_progress, symbol_lastP, &symbol_rootP, &symbol_lastP);
-
+      symbol_append (def_symbol_in_progress, symbol_lastP, &symbol_rootP,
+                    &symbol_lastP);
     }
   else
     {
-      /* This symbol already exists, merge the
-                  newly created symbol into the old one.
-                  This is not mandatory. The linker can
-                  handle duplicate symbols correctly. But I
-                  guess that it save a *lot* of space if
-                  the assembly file defines a lot of
-                  symbols. [loic] */
+      /* This symbol already exists, merge the newly created symbol
+        into the This is not mandatory. The linker can handle
+        duplicate symbols correctly. But I guess that it save a *lot*
+        of space if the assembly file defines a lot of
+        symbols. [loic] */
 
-      /* The debug entry (def_symbol_in_progress)
-                  is merged into the previous definition. */
+      /* The debug entry (def_symbol_in_progress) is merged into the
+        previous definition.  */
 
       c_symbol_merge (def_symbol_in_progress, symbolP);
       /* FIXME-SOON Should *def_symbol_in_progress be free'd? xoxorich. */
@@ -1012,13 +1019,16 @@ DEFUN_VOID (obj_coff_endef)
       if (SF_GET_FUNCTION (def_symbol_in_progress)
          || SF_GET_TAG (def_symbol_in_progress))
        {
-         /* For functions, and tags, the symbol *must* be where the debug symbol
-                          appears.  Move the existing symbol to the current place. */
+         /* For functions, and tags, the symbol *must* be where the
+            debug symbol appears.  Move the existing symbol to the
+            current place. */
          /* If it already is at the end of the symbol list, do nothing */
          if (def_symbol_in_progress != symbol_lastP)
            {
-             symbol_remove (def_symbol_in_progress, &symbol_rootP, &symbol_lastP);
-             symbol_append (def_symbol_in_progress, symbol_lastP, &symbol_rootP, &symbol_lastP);
+             symbol_remove (def_symbol_in_progress, &symbol_rootP,
+                            &symbol_lastP);
+             symbol_append (def_symbol_in_progress, symbol_lastP,
+                            &symbol_rootP, &symbol_lastP);
            }                   /* if not already in place */
        }                       /* if function */
     }                          /* normal or mergable */
@@ -1027,7 +1037,7 @@ DEFUN_VOID (obj_coff_endef)
       && symbol_find_base (S_GET_NAME (def_symbol_in_progress), DO_NOT_STRIP) == NULL)
     {
       tag_insert (S_GET_NAME (def_symbol_in_progress), def_symbol_in_progress);
-    }                          /* If symbol is a {structure,union} tag, associate symbol to its name. */
+    }
 
   if (SF_GET_FUNCTION (def_symbol_in_progress))
     {
@@ -1035,14 +1045,12 @@ DEFUN_VOID (obj_coff_endef)
       function_lineoff
        = c_line_new (def_symbol_in_progress, 0, 0, &zero_address_frag);
 
-
-
       SF_SET_PROCESS (def_symbol_in_progress);
 
       if (symbolP == NULL)
        {
-         /* That is, if this is the first
-                      time we've seen the function... */
+         /* That is, if this is the first time we've seen the
+            function... */
          symbol_table_insert (def_symbol_in_progress);
        }                       /* definition follows debug */
     }                          /* Create the line number entry pointing to the function being defined */
@@ -1050,7 +1058,7 @@ DEFUN_VOID (obj_coff_endef)
   def_symbol_in_progress = NULL;
   demand_empty_rest_of_line ();
   return;
-}                              /* obj_coff_endef() */
+}
 
 static void
 DEFUN_VOID (obj_coff_dim)
@@ -1099,7 +1107,7 @@ obj_coff_line ()
 
   if (def_symbol_in_progress == NULL)
     {
-      obj_coff_ln ();
+      obj_coff_ln (0);
       return;
     }                          /* if it looks like a stabs style line */
 
@@ -1234,11 +1242,15 @@ obj_coff_val ()
        }
       else if (strcmp (S_GET_NAME (def_symbol_in_progress), symbol_name))
        {
-         def_symbol_in_progress->sy_forward = symbol_find_or_make (symbol_name);
-
-         /* If the segment is undefined when the forward
-                          reference is solved, then copy the segment id
-                          from the forward symbol. */
+         def_symbol_in_progress->sy_value.X_op = O_symbol;
+         def_symbol_in_progress->sy_value.X_add_symbol =
+           symbol_find_or_make (symbol_name);
+         def_symbol_in_progress->sy_value.X_op_symbol = NULL;
+         def_symbol_in_progress->sy_value.X_add_number = 0;
+
+         /* If the segment is undefined when the forward reference is
+            resolved, then copy the segment id from the forward
+            symbol.  */
          SF_SET_GET_SEGMENT (def_symbol_in_progress);
 
          /* FIXME: gcc can generate address expressions
@@ -1346,12 +1358,12 @@ stack *block_stack;
 symbolS *last_functionP = NULL;
 symbolS *last_tagP;
 
-
 static unsigned int
 DEFUN_VOID (yank_symbols)
 {
   symbolS *symbolP;
   unsigned int symbol_number = 0;
+  unsigned int last_file_symno = 0;
 
   for (symbolP = symbol_rootP;
        symbolP;
@@ -1365,6 +1377,7 @@ DEFUN_VOID (yank_symbols)
          /* L* and C_EFCN symbols never merge. */
          if (!SF_GET_LOCAL (symbolP)
              && S_GET_STORAGE_CLASS (symbolP) != C_LABEL
+             && symbolP->sy_value.X_op == O_constant
              && (real_symbolP = symbol_find_base (S_GET_NAME (symbolP), DO_NOT_STRIP))
              && real_symbolP != symbolP)
            {
@@ -1391,8 +1404,7 @@ DEFUN_VOID (yank_symbols)
              S_SET_SEGMENT (symbolP, SEG_E0);
            }                   /* push data into text */
 
-         S_SET_VALUE (symbolP,
-                      S_GET_VALUE (symbolP) + symbolP->sy_frag->fr_address);
+         resolve_symbol_value (symbolP);
 
          if (!S_IS_DEFINED (symbolP) && !SF_GET_LOCAL (symbolP))
            {
@@ -1449,10 +1461,9 @@ DEFUN_VOID (yank_symbols)
                         sizeof (symbolP->sy_symbol.ost_auxent[0].x_sym.x_fcnary.x_ary.x_dimen));
 #endif
                }
-             /* The C_FCN doesn't need any additional information.
-              I don't even know if this is needed for sdb. But the
-              standard assembler generates it, so...
-              */
+             /* The C_FCN doesn't need any additional information.  I
+                don't even know if this is needed for sdb. But the
+                standard assembler generates it, so...  */
              if (S_GET_STORAGE_CLASS (symbolP) == C_EFCN)
                {
                  if (last_functionP == (symbolS *) 0)
@@ -1481,8 +1492,8 @@ DEFUN_VOID (yank_symbols)
        {
          if (S_GET_VALUE (symbolP))
            {
-             S_SET_VALUE ((symbolS *) S_GET_VALUE (symbolP), symbol_number);
-             S_SET_VALUE (symbolP, 0);
+             S_SET_VALUE (symbolP, last_file_symno);
+             last_file_symno = symbol_number;
            }                   /* no one points at the first .file symbol */
        }                       /* if debug or tag or eos or file */
 
@@ -1603,35 +1614,11 @@ DEFUN (crawl_symbols, (h, abfd),
 {
 
   unsigned int i;
-  unsigned int ptr = 0;
-
-
   symbolS *symbolP;
 
   /* Initialize the stack used to keep track of the matching .bb .be */
 
   block_stack = stack_init (512, sizeof (symbolS *));
-  /* JF deal with forward references first... */
-  for (symbolP = symbol_rootP;
-       symbolP;
-       symbolP = symbol_next (symbolP))
-    {
-
-      if (symbolP->sy_forward)
-       {
-         S_SET_VALUE (symbolP, (S_GET_VALUE (symbolP)
-                                + S_GET_VALUE (symbolP->sy_forward)
-                              + symbolP->sy_forward->sy_frag->fr_address));
-
-         if (SF_GET_GET_SEGMENT (symbolP))
-           {
-             S_SET_SEGMENT (symbolP, S_GET_SEGMENT (symbolP->sy_forward));
-           }                   /* forward segment also */
-
-         symbolP->sy_forward = 0;
-       }                       /* if it has a forward reference */
-    }                          /* walk the symbol chain */
-
 
   /* The symbol list should be ordered according to the following sequence
    * order :
@@ -1692,8 +1679,8 @@ DEFUN (w_strings, (where),
   symbolS *symbolP;
 
   /* Gotta do md_ byte-ordering stuff for string_byte_count first - KWK */
-  md_number_to_chars (where, string_byte_count, sizeof (string_byte_count));
-  where += sizeof (string_byte_count);
+  md_number_to_chars (where, string_byte_count, 4);
+  where += 4;
   for (symbolP = symbol_rootP;
        symbolP;
        symbolP = symbol_next (symbolP))
@@ -1956,11 +1943,11 @@ DEFUN (change_to_section, (name, len, exp),
        {
          subseg_new (i, exp);
          return;
-
        }
     }
   /* No section, add one */
   strncpy (segment_info[i].scnhdr.s_name, name, 8);
+  segment_info[i].scnhdr.s_flags = STYP_REG;
   subseg_new (i, exp);
 }
 
@@ -2060,7 +2047,10 @@ obj_coff_text ()
 static void
 obj_coff_data ()
 {
-  change_to_section (".data", 5, get_absolute_expression ());
+  if (flagseen['R'])
+    change_to_section (".text", 5, get_absolute_expression () + 1000);
+  else
+    change_to_section (".data", 5, get_absolute_expression ());
 }
 
 static void
@@ -2500,8 +2490,14 @@ DEFUN (fixup_segment, (segP, this_segment_type),
                  break;
                default:
 
+#ifdef TC_A29K
+                 /* This really should be handled in the linker, but
+                    backward compatibility forbids.  */
+                 add_number += S_GET_VALUE (add_symbolP);
+#else
                  add_number += S_GET_VALUE (add_symbolP) +
                    segment_info[S_GET_SEGMENT (add_symbolP)].scnhdr.s_paddr;
+#endif
                  break;
 
                case SEG_UNKNOWN:
@@ -2536,7 +2532,11 @@ DEFUN (fixup_segment, (segP, this_segment_type),
 
       if (pcrel)
        {
+#ifndef TC_M88K
+         /* This adjustment is not correct on the m88k, for which the
+            linker does all the computation.  */
          add_number -= md_pcrel_from (fixP);
+#endif
          if (add_symbolP == 0)
            {
              fixP->fx_addsy = &abs_symbol;
@@ -2550,6 +2550,9 @@ DEFUN (fixup_segment, (segP, this_segment_type),
 
       if (!fixP->fx_bit_fixP)
        {
+#ifndef TC_M88K
+         /* The m88k uses the offset field of the reloc to get around
+            this problem.  */
          if ((size == 1 &&
          (add_number & ~0xFF) && ((add_number & ~0xFF) != (-1 & ~0xFF))) ||
              (size == 2 &&
@@ -2558,6 +2561,7 @@ DEFUN (fixup_segment, (segP, this_segment_type),
              as_bad ("Value of %d too large for field of %d bytes at 0x%x",
                      add_number, size, fragP->fr_address + where);
            }                   /* generic error checking */
+#endif
 #ifdef WARN_SIGNED_OVERFLOW_WORD
          /* Warn if a .word value is too large when treated as
             a signed number.  We already know it is not too