diff -r -u binutils-2.9.4.0.7.hjlu/gas/config/tc-i370.c binutils-2.9.4.0.7/gas/config/tc-i370.c
--- binutils-2.9.4.0.7.hjlu/gas/config/tc-i370.c	Sun Jun  6 19:29:50 1999
+++ binutils-2.9.4.0.7/gas/config/tc-i370.c	Tue Jul 13 23:55:43 1999
@@ -105,7 +105,7 @@
 static void i370_ltorg PARAMS ((int));
 static void i370_using PARAMS ((int));
 static void i370_drop PARAMS ((int));
-static void i370_make_relative PARAMS ((expressionS *exp));
+static void i370_make_relative PARAMS ((expressionS *exp, expressionS *baseaddr));
 
 #ifdef OBJ_ELF
 static bfd_reloc_code_real_type i370_elf_suffix PARAMS ((char **, expressionS *));
@@ -385,11 +385,34 @@
    I370_OPCODE_32 or I370_OPCODE_64.  */
 static int i370_size = I370_OPCODE_32;
 
-/* The base register to use for opcode with optional operands */ 
-static int i370_using_regno = -1;
+/* 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"
+ * gets used in the .data section for address constants.  
+ *
+ * The idea of a second base register in a different section
+ * is foreign to the usual HLASM-style semantics; however, it
+ * allows us to provide support for dynamically loaded libraries,
+ * by allowing us to place address constants in a section other 
+ * than the text section. The "other" section need not be the 
+ * .data section, it can be any section that isn't the .text section.
+ *
+ * Note that HLASM defines a multiple, concurrent .using semantic
+ * that we do not: in calculating offsets, it uses either the most 
+ * recent .using directive, or the one with the smallest displacement.
+ * This allows HLASM to support a quasi-block-scope-like behaviour.
+ * Handy for people writing assembly by hand ... but not supported 
+ * by us.
+ */ 
+static int i370_using_text_regno = -1;
+static int i370_using_other_regno = -1;
 
 /* The base address for address literals */
-static expressionS i370_using_baseaddr;
+static expressionS i370_using_text_baseaddr;
+static expressionS i370_using_other_baseaddr;
+
+/* the "other" section, used only for syntax error detection */
+static segT i370_other_section = undefined_section;
 
 /* Opcode hash table.  */
 static struct hash_control *i370_hash;
@@ -1030,23 +1053,23 @@
 i370_dsect (xxx)
      int xxx; 
 {
-  as_tsktsk ("dsect not supported");
-}
-
-static void
-i370_csect (xxx)
-     int xxx; 
-{
   char *save_line = input_line_pointer;
-  static char section[] = ".text\n";
+  static char section[] = ".data\n";
 
-  /* Just pretend this is .section .text */
+  /* Just pretend this is .section .data */
   input_line_pointer = section;
   obj_elf_section (xxx);
 
   input_line_pointer = save_line;
 }
 
+static void
+i370_csect (xxx)
+     int xxx; 
+{
+  as_tsktsk ("csect not supported");
+}
+
 
 /* DC Define Const  is only partially supported.
  * For samplecode on what to do, look at i370_elf_cons() above.
@@ -1442,7 +1465,17 @@
   else if (1 == sz) exx->X_add_symbol = byte_poolP;
   exx->X_add_number = offset_in_pool;
   exx->X_op_symbol = NULL;
-  i370_make_relative (exx);
+
+  /* If the user has set up a base reg in another section,
+   * use that; otherwise use the text section.  */
+  if (0 < i370_using_other_regno) 
+    {
+      i370_make_relative (exx, &i370_using_other_baseaddr);
+    } 
+  else 
+    {
+      i370_make_relative (exx, &i370_using_text_baseaddr);
+    }
 }
  
 /* The symbol setup for the literal pool is done in two steps.  First,
@@ -1556,7 +1589,15 @@
   expression (exx);
 
   /* OK, now we have to subtract the "using" location  */
-  i370_make_relative (exx);
+  /* normally branches appear in the text section only... */
+  if (text_section == now_seg || 0 > i370_using_other_regno) 
+    {
+      i370_make_relative (exx, &i370_using_text_baseaddr);
+    } 
+  else 
+    {
+      i370_make_relative (exx, &i370_using_other_baseaddr);
+    }
 
   /* put the * back */
   if (dot) *dot = '*';
@@ -1718,6 +1759,18 @@
   int biggest_align = 0;
   char pool_name[20];
 
+  if (now_seg != text_section &&
+      i370_other_section == undefined_section) 
+    {
+      as_bad (".ltorg without prior .using in section %s",
+        now_seg->name);
+    }
+  if (now_seg != text_section &&
+      i370_other_section != now_seg ) 
+    {
+       as_bad (".ltorg in section %s paired to .using in section %s",
+       now_seg->name, i370_other_section->name);
+    }
   if ((NULL == longlong_poolP) &&
       (NULL == word_poolP) &&
       (NULL == short_poolP) &&
@@ -1730,11 +1783,12 @@
  
   /* find largest literal .. 2 4 or 8 */
   lit_count = 0;
-  while (lit_count < next_literal_pool_place) {
-    if (biggest_literal_size < literals[lit_count].size) 
-        biggest_literal_size = literals[lit_count].size;
-    lit_count ++;
-  }
+  while (lit_count < next_literal_pool_place) 
+    {
+      if (biggest_literal_size < literals[lit_count].size) 
+          biggest_literal_size = literals[lit_count].size;
+      lit_count ++;
+    }
   if (2 == biggest_literal_size) biggest_align = 1;
   else if (4 == biggest_literal_size) biggest_align = 2;
   else if (8 == biggest_literal_size) biggest_align = 3;
@@ -1816,7 +1870,7 @@
 i370_using (ignore)
      int ignore;
 {
-  expressionS ex;
+  expressionS ex, baseaddr;
   int iregno;
   char *star;
 
@@ -1827,11 +1881,11 @@
 
   /* the first arg to using will usually be ".", but it can
    * be a more complex exprsssion too ... */
-  expression (&i370_using_baseaddr);
+  expression (&baseaddr);
   if (star) *star = '*';
-  if ((O_constant != i370_using_baseaddr.X_op) &&
-      (O_symbol   != i370_using_baseaddr.X_op) &&
-      (O_uminus   != i370_using_baseaddr.X_op))
+  if ((O_constant != baseaddr.X_op) &&
+      (O_symbol   != baseaddr.X_op) &&
+      (O_uminus   != baseaddr.X_op))
   {
     as_bad (".using: base address expression illegal or too complex");
   }
@@ -1843,19 +1897,17 @@
   demand_empty_rest_of_line ();
   iregno = ex.X_add_number;
 
-  /* if we were strict, we could check that the current 
-   * using was -1 and if not, flag it as a warning ... */
-  if (-1 != i370_using_regno) {
-    // In fact, there can be multiple usings outstanding;
-    // the most recent or the one with the least offset is
-    // the one that gets used.  We don't support this ...
-    // but don't print the error mesg,  the common
-    // usage doesn't mess things up but does print this msg.
-    //     as_tsktsk (".using %d without dropping %d first", 
-    //       iregno, i370_using_regno);
-  }
-
-  i370_using_regno = iregno;
+  if (text_section == now_seg) 
+    {
+      i370_using_text_baseaddr = baseaddr;
+      i370_using_text_regno = iregno;
+    } 
+  else 
+    {
+      i370_using_other_baseaddr = baseaddr;
+      i370_using_other_regno = iregno;
+      i370_other_section = now_seg;
+    }
 }
 
 static void
@@ -1869,37 +1921,62 @@
   demand_empty_rest_of_line ();
   iregno = ex.X_add_number;
 
-  if (iregno != i370_using_regno) {
-    as_bad ("droping register %d does not match using register %d", 
-      iregno, i370_using_regno);
-  }
-  i370_using_regno = -1;
-  i370_using_baseaddr.X_op = O_absent;
+  if (text_section == now_seg) 
+    {
+      if (iregno != i370_using_text_regno) 
+        {
+          as_bad ("droping register %d in section %s does not match using register %d", 
+            iregno, now_seg->name, i370_using_text_regno);
+        }
+      i370_using_text_regno = -1;
+      i370_using_text_baseaddr.X_op = O_absent;
+    } 
+  else 
+    {
+      if (iregno != i370_using_other_regno) 
+        {
+          as_bad ("droping register %d in section %s does not match using register %d", 
+            iregno, now_seg->name, i370_using_other_regno);
+        }
+      if (i370_other_section != now_seg) 
+        {
+          as_bad ("droping register %d in section %s previously used in section %s",
+            iregno, now_seg->name, i370_other_section->name);
+        }
+      i370_using_other_regno = -1;
+      i370_using_other_baseaddr.X_op = O_absent;
+      i370_other_section = undefined_section;
+    }
 }
 
+/* Make the first argument an address-relative expression
+ * by subtracting the second argument.
+ */
 static void
-i370_make_relative (expressionS *exx)
+i370_make_relative (expressionS *exx, expressionS *baseaddr)
 {
-  if (O_constant == i370_using_baseaddr.X_op) 
-  {
-     exx->X_op = O_symbol;
-     exx->X_add_number -= i370_using_baseaddr.X_add_number;
-  } else
-  if (O_symbol == i370_using_baseaddr.X_op) 
-  {
-     exx->X_op = O_subtract;
-     exx->X_op_symbol = i370_using_baseaddr.X_add_symbol;
-     exx->X_add_number -= i370_using_baseaddr.X_add_number;
-  } else
-  if (O_uminus == i370_using_baseaddr.X_op) 
-  {
-     exx->X_op = O_add;
-     exx->X_op_symbol = i370_using_baseaddr.X_add_symbol;
-     exx->X_add_number += i370_using_baseaddr.X_add_number;
-   } else 
-   {
-      as_bad ("Missing or bad .using directive");
-   }
+
+  if (O_constant == baseaddr->X_op) 
+    {
+       exx->X_op = O_symbol;
+       exx->X_add_number -= baseaddr->X_add_number;
+    } 
+  else if (O_symbol == baseaddr->X_op) 
+    {
+       exx->X_op = O_subtract;
+       exx->X_op_symbol = baseaddr->X_add_symbol;
+       exx->X_add_number -= baseaddr->X_add_number;
+    } 
+  else if (O_uminus == baseaddr->X_op) 
+    {
+       exx->X_op = O_add;
+       exx->X_op_symbol = baseaddr->X_add_symbol;
+       exx->X_add_number += baseaddr->X_add_number;
+     } 
+  else 
+     {
+        as_bad ("Missing or bad .using directive");
+     }
 }
 
 /* We need to keep a list of fixups.  We can't simply generate them as
@@ -1927,6 +2004,7 @@
   const unsigned char *opindex_ptr;
   int have_optional_index, have_optional_basereg, have_optional_reg;
   int skip_optional_index, skip_optional_basereg, skip_optional_reg;
+  int use_text=0, use_other=0;
   int off_by_one;
   int need_paren = 0;
   struct i370_fixup fixups[MAX_INSN_FIXUPS];
@@ -2074,10 +2152,34 @@
       if (skip_optional_basereg && 
           ((operand->flags & I370_OPERAND_BASE) != 0))
         {
-          if (0 > i370_using_regno) {
-            as_bad ("not using any base register");
-          }
-          insn = i370_insert_operand (insn, operand, i370_using_regno,
+          int basereg = -1;
+          if (use_text) 
+            {
+              if (text_section == now_seg || 0 > i370_using_other_regno) 
+                {
+                  basereg = i370_using_text_regno;
+                } 
+              else 
+                {
+                  basereg = i370_using_other_regno;
+                } 
+            }
+          else if (use_other) 
+            {
+              if (0 > i370_using_other_regno) 
+                {
+                  basereg = i370_using_text_regno;
+                } 
+              else 
+                {
+                  basereg = i370_using_other_regno;
+                } 
+            }
+          if (0 > basereg) 
+            {
+              as_bad ("not using any base register");
+            }
+          insn = i370_insert_operand (insn, operand, basereg,
         			     (char *) NULL, 0);
           continue;
         }
@@ -2113,8 +2215,10 @@
         }
 
       /* check for a address constant expression */
-      else if (i370_addr_cons (&ex)) {}
-      else if (i370_addr_offset (&ex)) {}
+      /* We will put PSW-relative addresses in the text section,
+       * and adress literals in the .data (or other) section. */
+      else if (i370_addr_cons (&ex)) { use_other=1; }
+      else if (i370_addr_offset (&ex)) { use_text=1; }
       else expression (&ex);
 
       str = input_line_pointer;
diff -r -u binutils-2.9.4.0.7.hjlu/gas/doc/c-i370.texi binutils-2.9.4.0.7/gas/doc/c-i370.texi
--- binutils-2.9.4.0.7.hjlu/gas/doc/c-i370.texi	Sat Jun  5 20:50:54 1999
+++ binutils-2.9.4.0.7/gas/doc/c-i370.texi	Tue Jul 13 23:57:03 1999
@@ -25,16 +25,18 @@
 
 @node ESA/390 Notes
 @section Notes
-As a back end for @sc{gnu} @sc{cc} @code{@value{AS}} has been tested 
-but should still be considered experimental.  It will not work with 
-HLASM-style assembly because it supports only a small subset of the 
-HLASM directives.  Note that that only ELF-style binary file formats are
-supported; none of the usual MVS/VM/OE/USS object file formats are
-supported.
-
-The ESA/390 @code{@value{AS}} port generates only a 31-bit relocation;
-many more are available in the ELF object file format but are not
-supported, and may fail silently.
+The ESA/390 @code{@value{AS}} port is currently intended to be a back-end
+for the @sc{gnu} @sc{cc} compiler.  It is not HLASM compatible, although
+it does support a subset of some of the HLASM directives.  The only 
+supported binary file format is ELF; none of the usual MVS/VM/OE/USS 
+object file formats, such as ESD or XSD, are supported.
+
+When used with the @sc{gnu} @sc{cc} compiler, the ESA/390 @code{@value{AS}}
+will produce correct, fully relocated, functional binaries, and has been 
+used to compile and execute large projects.  However, many aspects should 
+still be considered experimental; these include shared library support, 
+dynamically loadable objects, and any relocation other than the 31-bit 
+relocation.
 
 @node ESA/390 Options
 @section Options
@@ -49,7 +51,7 @@
 are @emph{not} supported for the most part, with the exception of those 
 described herein.
 
-A leading dot in front of directives is optional, and teh case of
+A leading dot in front of directives is optional, and the case of
 directives is ignored; thus for example, .using and USING have the same
 effect.
 
@@ -121,7 +123,9 @@
 A small subset of the usual DC directive is supported.
 
 @item .drop @var{regno}
-Stop using @var{regno} as the base register.
+Stop using @var{regno} as the base register.  The @var{regno} must
+have been previously declared with a @code{.using} directive in the
+same section as the current section.
 
 @item .ebcdic @var{string}
 Emit the EBCDIC equivalent of the indicated string.  The emitted string
@@ -134,11 +138,60 @@
 
 @item .ltorg 
 Dump the literal pool accumulated so far; begin a new literal pool.
+The literal pool will be written in the current section; in order to
+generate correct assembly, a @code{.using} must have been previously
+specified in the same section.
 
 @item .using @var{expr},@var{regno}
 Use @var{regno} as the base register for all subsequent RX, RS, and SS form
 instructions. The @var{expr} will be evaluated to obtain the base address;
 usually, @var{expr} will merely be @samp{*}.
+
+This assembler allows two @code{.using} directives to be simultaneously
+outstanding, one in the @code{.text} section, and one in another section 
+(typically, the @code{.data} section).  This feature allows 
+dynamically loaded objects to be implemented in a relatively 
+straightforward way.  A @code{.using} directive must always be specified 
+in the @code{.text} section; this will specify the base register that
+will be used for branches in the @code{.text} section.  A second
+@code{.using} may be specified in another section; this will specify
+the base register that is used for non-label address literals.
+When a second @code{.using} is specified, then the subsequent
+@code{.ltorg} must be put in the same section; otherwise an error will 
+result.
+
+Thus, for example, the following code uses @code{r3} to address branch 
+targets and @code{r4} to address the literal pool, which has been written 
+to the @code{.data} section.  The is, the constants @code{=A(some_routine)},
+@code{=H'42'} and @code{=E'3.1416'} will all appear in the @code{.data}
+section.
+
+@example
+.data
+	.using  LITPOOL,r4
+.text
+	BASR	r3,0
+	.using	*,r3
+        B       START
+	.long	LITPOOL
+START:
+	L	r4,4(,r3)
+	L	r15,=A(some_routine)
+	LTR	r15,r15
+	BNE	LABEL
+	AH	r0,=H'42'
+LABEL:
+	ME	r6,=E'3.1416'
+.data
+LITPOOL:
+	.ltorg
+@end example
+
+
+Note that this dual-@code{.using} directive semantics extends 
+and is not compatible with HLASM semantics.  Note that this assembler 
+directive does not support the full range of HLASM semantics.
+
 @end table
 
 @node ESA/390 Opcodes
