--- binutils-2.9.5.0.13hjlu/gas/config/tc-i370.c	Wed Sep 22 17:13:11 1999
+++ binutils-2.9.5.0.12/gas/config/tc-i370.c	Wed Sep 22 00:45:15 1999
@@ -31,6 +31,7 @@
 #include <ctype.h>
 #include "as.h"
 #include "subsegs.h"
+#include "struc-symbol.h"
 
 #include "opcode/i370.h"
 
@@ -381,10 +382,6 @@
    of the I370_OPCODE flags defined in opcode/i370.h.  */
 static int i370_cpu = 0;
 
-/* The size of the processor we are assembling for.  This is either
-   I370_OPCODE_32 or I370_OPCODE_64.  */
-static int i370_size = 0;
-
 /* The base register to use for opcode with optional operands.
  * We define two of these: "text" and "other".  Normally, "text"
  * would get used in the .text section for branches, while "other"
@@ -657,60 +654,6 @@
      char *file;
      unsigned int line;
 {
-//   if (operand->bits != 32)
-//     {
-//       long min, max;
-//       offsetT test;
-// 
-//       if ((operand->flags & PPC_OPERAND_SIGNED) != 0)
-//         {
-//           if ((operand->flags & PPC_OPERAND_SIGNOPT) != 0
-//               && ppc_size == PPC_OPCODE_32)
-//             max = (1 << operand->bits) - 1;
-//           else
-//             max = (1 << (operand->bits - 1)) - 1;
-//           min = - (1 << (operand->bits - 1));
-// 
-//           if (ppc_size == PPC_OPCODE_32)
-//             {
-//               /* Some people write 32 bit hex constants with the sign
-//         	 extension done by hand.  This shouldn't really be
-//         	 valid, but, to permit this code to assemble on a 64
-//         	 bit host, we sign extend the 32 bit value.  */
-//               if (val > 0
-//         	  && (val & 0x80000000) != 0
-//         	  && (val & 0xffffffff) == val)
-//         	{
-//         	  val -= 0x80000000;
-//         	  val -= 0x80000000;
-//         	}
-//             }
-//         }
-//       else
-//         {
-//           max = (1 << operand->bits) - 1;
-//           min = 0;
-//         }
-// 
-//       if ((operand->flags & PPC_OPERAND_NEGATIVE) != 0)
-//         test = - val;
-//       else
-//         test = val;
-// 
-//       if (test < (offsetT) min || test > (offsetT) max)
-//         {
-//           const char *err =
-//             "operand out of range (%s not between %ld and %ld)";
-//           char buf[100];
-// 
-//           sprint_value (buf, test);
-//           if (file == (char *) NULL)
-//             as_bad (err, buf, min, max);
-//           else
-//             as_bad_where (file, line, err, buf, min, max);
-//         }
-//     }
-
   if (operand->insert)
     {
       const char *errmsg;
@@ -766,26 +709,7 @@
 //     MAP ("l",        	BFD_RELOC_LO16),
 //     MAP ("h",        	BFD_RELOC_HI16),
 //     MAP ("ha",        	BFD_RELOC_HI16_S),
-//     MAP ("got",        	BFD_RELOC_16_GOTOFF),
-//     MAP ("got@l",        BFD_RELOC_LO16_GOTOFF),
-//     MAP ("got@h",        BFD_RELOC_HI16_GOTOFF),
-//     MAP ("got@ha",        BFD_RELOC_HI16_S_GOTOFF),
     MAP ("fixup",        BFD_RELOC_CTOR),          /* warnings with -mrelocatable */
-//     MAP ("plt",		BFD_RELOC_24_PLT_PCREL),
-//     MAP ("pltrel24",		BFD_RELOC_24_PLT_PCREL),
-//     MAP ("plt@l",		BFD_RELOC_LO16_PLTOFF),
-//     MAP ("plt@h",		BFD_RELOC_HI16_PLTOFF),
-//     MAP ("plt@ha",		BFD_RELOC_HI16_S_PLTOFF),
-//     MAP ("copy",        BFD_RELOC_PPC_COPY),
-
-//     MAP ("globdat",        BFD_RELOC_PPC_GLOB_DAT),
-//     MAP ("pltrel",        BFD_RELOC_32_PLT_PCREL),
-//     MAP ("sdarel",        BFD_RELOC_GPREL16),
-//     MAP ("sectoff",        BFD_RELOC_32_BASEREL),
-//     MAP ("sectoff@l",        BFD_RELOC_LO16_BASEREL),
-//     MAP ("sectoff@h",        BFD_RELOC_HI16_BASEREL),
-//     MAP ("sectoff@ha",        BFD_RELOC_HI16_S_BASEREL),
-// 
     { (char *)0,        0,	BFD_RELOC_UNUSED }
    };
 
@@ -2269,10 +2193,6 @@
         	/* X_unsigned is the default, so if the user has done
                    something which cleared it, we always produce a
                    signed value.  */
-//        	if (ex.X_unsigned
-//         	    && (operand->flags & PPC_OPERAND_SIGNED) == 0)
-//         	  ex.X_add_number &= 0xffff;
-//         	else
          	  ex.X_add_number = (((ex.X_add_number & 0xffff)
         			      ^ 0x8000)
         			     - 0x8000);
@@ -2322,30 +2242,6 @@
           ++fc;
         }
 
-// it might be nice to dust off this code to get nitpicky about parenthesis,
-// but laziness sets in right about now ...
-//       if (need_paren)
-//         {
-//           endc = ')';
-//           need_paren = 0;
-//         }
-//       else if ((operand->flags & I370_OPERAND_PARENS) != 0)
-//         {
-//           endc = '(';
-//           need_paren = 1;
-//         }
-//       else
-//         endc = ',';
-// 
-//       /* The call to expression should have advanced str past any
-//          whitespace.  */
-//       if (*str != endc
-//           && (endc != ',' || *str != '\0'))
-//         {
-//           as_bad ("syntax error; found `%c' but expected `%c'", *str, endc);
-//           break;
-//         }
- 
        /* skip over delimiter (close paren, or comma) */
        if ((')' == *str) && (',' == *(str+1))) ++str;
        if (*str != '\0') ++str;
@@ -2788,103 +2684,56 @@
 {
   valueT value;
 
-#ifdef OBJ_ELF
   value = *valuep;
   if (fixp->fx_addsy != NULL)
     {
-#ifdef DEBUG 
-      printf ("\nmd_apply_fix3: symbol %s at %s:%d addend=0x%x\n", 
-            bfd_asymbol_name (fixp->fx_addsy->bsym),
-            fixp->fx_file, fixp->fx_line,
-            value);
-#endif 
-
-      /* if its a difference between two symbols in the same section,
-       * there is nothing to be done, no relocation to be performed.
-       */
-      if (fixp->fx_subsy != NULL)
-        {
-          if ((S_GET_SEGMENT(fixp->fx_addsy) ==  S_GET_SEGMENT(fixp->fx_subsy))
-              && (undefined_section != S_GET_SEGMENT(fixp->fx_addsy)))
-            {
-// printf ("duuuuuuuuuuuuuuuuuuuuuuuuude %x %x  %d %d %s\n",
-// S_GET_VALUE (fixp->fx_addsy),
-// S_GET_VALUE (fixp->fx_subsy),
-// fixp->fx_addsy->sy_used_in_reloc,
-// fixp->fx_subsy->sy_used_in_reloc,
-// bfd_asymbol_value(fixp->fx_addsy->bsym),
-// bfd_asymbol_value(fixp->fx_subsy->bsym),
-// S_IS_DEFINED (fixp->fx_addsy),
-// S_IS_DEFINED (fixp->fx_subsy),
-// fixp->fx_addsy->sy_resolved,
-// fixp->fx_subsy->sy_resolved,
-// segment_name( S_GET_SEGMENT (fixp->fx_addsy)) ,
-// segment_name( S_GET_SEGMENT (fixp->fx_subsy)),
-// fixp->fx_subsy->bsym->name);
-
-// stupid blasted code is telling me that things in the literal pool 
-// are differences of a pair of symbols, and clearly that's not what I wanted
-// ... what is the gig .... ??
-// BTW, nmote that S_GET_VALUE (fixp->fx_subsy) is the address of the 
-// .using used to construct the adress literal.
-//
-// well, here's my very cheesy hack: all I care about are expressions
-// of the form .LFDSL01-.LFDSE01 so if the first two chars are .L we assume
-// its just a plain old difference.
-// unfortunately, this screws up other relocations ... help !!
-#ifdef JUNK
-              if (('.' == fixp->fx_subsy->bsym->name[0]) &&
-                  ('L' == fixp->fx_subsy->bsym->name[1]))
-              {
-                 fixp->fx_done = 1;
-                 return 1;
-              }
-#endif  /* JUNK */
-            }
-        }
+      /* Notes:
+         Branches to labels will come in here with fixp->fx_pcrel set to 1
+         and fixp->fx_subsy not null, and holding the value of the base
+         (i.e. the value of the .using). These we want to ignore.  
+
+         'Strong' and 'weak' symbols will come in here with 
+         fixp->fx_pcrel==0, fixp->fx_addsy defined, and
+         *valuep holding the value of the symbol.
+
+         'Strong' symbols will have S_GET_VALUE(fx_addsy) equal to zero, 
+         whereas 'weak' symbols will have S_GET_VALUE(fx_addsy) set to the
+         symbol value (usually).
+
+         We want to subtract S_GET_VALUE(fx_addsy) if it set, and
+         for all practical purposes, do a fixup with value zero.  This 
+         is because the linker/loader, at a later time, will do this
+         fixup with the correct value. If we fixup now with a value,
+         it will get double-fixed, leading to garbage.    
+
+         Note that subsy will also be set for strong/weak symbols 
+         when the user program was compiled with -g.  In that case,
+         subsy will hold the base address (i.e. the .using address).
+         */
 
-#ifdef JUNK 
-      /* `*valuep' may contain the value of the symbol on which the reloc
-         will be based; we have to remove it.  */
       if (fixp->fx_addsy->sy_used_in_reloc
           && S_GET_SEGMENT (fixp->fx_addsy) != absolute_section
           && S_GET_SEGMENT (fixp->fx_addsy) != undefined_section
           && ! bfd_is_com_section (S_GET_SEGMENT (fixp->fx_addsy)))
         value -= S_GET_VALUE (fixp->fx_addsy);
 
-printf ("addsy value is %x \n", S_GET_VALUE (fixp->fx_addsy));
-printf ("value now %x \n", value);
-      /* FIXME: Why '+'?  Better yet, what exactly is '*valuep'
-         supposed to be?  I think this is related to various similar
-         FIXMEs in tc-i386.c and tc-sparc.c and tc-ppc.c.  */
-      if (fixp->fx_pcrel)
-        value += fixp->fx_frag->fr_address + fixp->fx_where;
-printf ("pcrel value is %x \n", fixp->fx_frag->fr_address + fixp->fx_where);
-printf ("value now %x \n", value);
-#endif /* JUNK */
-
-        /* OK, heres the deal:
-         * S_GET_VALUE (fixp->fx_addsy) is the offset of the symbol 
-         *    relative to whatever section that symbol is in.
-         * fixp->fx_frag->fr_address + fixp->fx_where is the offset
-         *    of the instruction to whatever section it is in.
-         *
-         * Until we figure out what our ABI will be, we'll hard-code 
-         * the symbol address and punt.
-         */
-        // value = S_GET_VALUE (fixp->fx_addsy);
+#ifdef DEBUG 
+      printf ("\nmd_apply_fix3: symbol %s at 0x%x (%s:%d) val=0x%x addend=0x%x\n", 
+            S_GET_NAME (fixp->fx_addsy),
+            fixp->fx_frag->fr_address + fixp->fx_where,
+            fixp->fx_file, fixp->fx_line,
+            S_GET_VALUE (fixp->fx_addsy), value);
+#endif 
     }
   else
     {
       fixp->fx_done = 1;
       return 1;
     }
-#endif
 
-  /* apply fixups to operands.  Note that there should be no relocations
-   * for any operands, since no instruction ever takes an operand
-   * that requires reloc.
-   */
+  /* Apply fixups to operands.  Note that there should be no relocations
+     for any operands, since no instruction ever takes an operand
+     that requires reloc.  */
   if ((int) fixp->fx_r_type >= (int) BFD_RELOC_UNUSED)
     {
       int opindex;
@@ -2929,15 +2778,16 @@
        /* Determine a BFD reloc value based on the operand information.
           We are only prepared to turn a few of the operands into
           relocs.  In fact, we support *zero* operand relocations ...
-          Why?  because we are not expecting the compiler to generate
-          any operands that need relocation.
-        */
-
-//      if ((operand->flags & I370_OPERAND_RELATIVE) != 0
-//          && operand->bits == 12
-//          && operand->shift == 0)
-//        fixp->fx_r_type = BFD_RELOC_I370_D12;
-//      else
+          Why?  Because we are not expecting the compiler to generate
+          any operands that need relocation.  Due to the 12-bit naturew of
+          i370 addressing, this would be unusual. */
+#if 0
+      if ((operand->flags & I370_OPERAND_RELATIVE) != 0
+          && operand->bits == 12
+          && operand->shift == 0)
+        fixp->fx_r_type = BFD_RELOC_I370_D12;
+      else
+#endif
         {
           char *sfile;
           unsigned int sline;
@@ -2977,9 +2827,9 @@
         				/* fall through */
 
         case BFD_RELOC_RVA:
-//         case BFD_RELOC_32_PCREL:
-//         case BFD_RELOC_32_BASEREL:
-#ifdef DEBUG
+        case BFD_RELOC_32_PCREL:
+        case BFD_RELOC_32_BASEREL:
+ #ifdef DEBUG
           printf ("\t32 bit relocation at 0x%x\n",
                 fixp->fx_frag->fr_address + fixp->fx_where);
  #endif 
@@ -2989,16 +2839,6 @@
 
         case BFD_RELOC_LO16:
         case BFD_RELOC_16:
-//         case BFD_RELOC_GPREL16:
-//         case BFD_RELOC_16_GOT_PCREL:
-//         case BFD_RELOC_16_GOTOFF:
-//         case BFD_RELOC_LO16_GOTOFF:
-//         case BFD_RELOC_HI16_GOTOFF:
-//         case BFD_RELOC_HI16_S_GOTOFF:
-//         case BFD_RELOC_LO16_BASEREL:
-//         case BFD_RELOC_HI16_BASEREL:
-//         case BFD_RELOC_HI16_S_BASEREL:
-//         case BFD_RELOC_PPC_TOC16:
           if (fixp->fx_pcrel)
             as_bad_where (fixp->fx_file, fixp->fx_line,
         		  "cannot emit PC relative %s relocation%s%s",
@@ -3025,7 +2865,7 @@
           if (fixp->fx_pcrel)
             abort ();
           md_number_to_chars (fixp->fx_frag->fr_literal + fixp->fx_where,
-        		      value + 0x8000 >> 16, 2);
+        		      (value + 0x8000) >> 16, 2);
           break;
 
         case BFD_RELOC_8:
@@ -3035,37 +2875,6 @@
           md_number_to_chars (fixp->fx_frag->fr_literal + fixp->fx_where,
         		      value, 1);
           break;
-
-//         case BFD_RELOC_24_PLT_PCREL:
-//         case BFD_RELOC_PPC_LOCAL24PC:
-//           if (!fixp->fx_pcrel && !fixp->fx_done)
-//             abort ();
-// 
-//           if (fixp->fx_done)
-//           {
-//             char *where;
-//             unsigned long insn;
-//             
-//             /* Fetch the instruction, insert the fully resolved operand
-//                value, and stuff the instruction back again.  */
-//             where = fixp->fx_frag->fr_literal + fixp->fx_where;
-//             if (target_big_endian)
-//               insn = bfd_getb32 ((unsigned char *) where);
-//             else
-//               insn = bfd_getl32 ((unsigned char *) where);
-//             if ((value & 3) != 0)
-//               as_bad_where (fixp->fx_file, fixp->fx_line,
-//         		    "must branch to an address a multiple of 4");
-//             if ((offsetT) value < -0x40000000
-//         	|| (offsetT) value >= 0x40000000)
-//               as_bad_where (fixp->fx_file, fixp->fx_line,
-//         		    "@local or @plt branch destination is too far "
-//         		    "away, %ld bytes",
-//         		    value);
-//             insn = insn | (value & 0x03fffffc);
-//             bfd_putb32 ((bfd_vma) insn, (unsigned char *) where);
-//           }
-//           break;
 
         default:
           fprintf(stderr,
