Changes to let cons handle bignums like general expressions.
authorIan Lance Taylor <ian@airs.com>
Wed, 6 Oct 1993 17:31:31 +0000 (17:31 +0000)
committerIan Lance Taylor <ian@airs.com>
Wed, 6 Oct 1993 17:31:31 +0000 (17:31 +0000)
* expr.h (expressionS): New field X_unsigned.
* expr.c (operand): Initialize X_unsigned to 1.  Set it to 0 for
unary minus case.
(expr) Fix typo resultP to right if missing operand.  Set
X_unsigned to 1 when building new expression.
* read.c (potable): Make "octa" and "quad" call cons, not
big_cons.
(cons): Handle bignums.  If given an O_constant (small integer) to
fill a big space, turn it into a bignum.
(parse_bitfield_cons): Set X_unsigned field.
(bignum_low, bignum_limit, bignum_high, grow_bignum, big_cons):
Removed.
* read.h (big_cons): Remove prototype.
* symbols.c (resolve_symbol_value): Don't give a warning if a
symbol in expr_section can not be resolved.
(S_SET_VALUE): Clear X_unsigned.
* write.c (write_object_file): If resolve_symbol_value failed on a
symbol we are writing out, give a warning.
* config/tc-h8500.c (parse_reglist): Set X_unsigned.
* config/tc-hppa.c (md_pseudo_table): Change "octa" and "quad" to
call pa_cons, not pa_big_cons.
(pa_big_cons): Remove.
* config/tc-hppa.h (pa_big_cons): Remove declaration.
* config/tc-i960.c (md_pseudo_table): Change "quad" to call cons,
not big_cons.

gas/ChangeLog
gas/config/tc-h8500.c
gas/config/tc-hppa.c
gas/config/tc-i960.c
gas/read.c
gas/write.c

index 7d94f43025f14539737f83d4000703c8decd6959..4a5e80bea94903e715d54fdbde619d0320095b77 100644 (file)
@@ -1,3 +1,37 @@
+Wed Oct  6 13:01:34 1993  Ian Lance Taylor  (ian@tweedledumb.cygnus.com)
+
+       Changes to let cons handle bignums like general expressions.
+       * expr.h (expressionS): New field X_unsigned.
+       * expr.c (operand): Initialize X_unsigned to 1.  Set it to 0 for
+       unary minus case.
+       (expr) Fix typo resultP to right if missing operand.  Set
+       X_unsigned to 1 when building new expression.
+       * read.c (potable): Make "octa" and "quad" call cons, not
+       big_cons.
+       (cons): Handle bignums.  If given an O_constant (small integer) to
+       fill a big space, turn it into a bignum.
+       (parse_bitfield_cons): Set X_unsigned field.
+       (bignum_low, bignum_limit, bignum_high, grow_bignum, big_cons):
+       Removed.
+       * read.h (big_cons): Remove prototype.
+       * symbols.c (resolve_symbol_value): Don't give a warning if a
+       symbol in expr_section can not be resolved.
+       (S_SET_VALUE): Clear X_unsigned.
+       * write.c (write_object_file): If resolve_symbol_value failed on a
+       symbol we are writing out, give a warning.
+       * config/tc-h8500.c (parse_reglist): Set X_unsigned.
+       * config/tc-hppa.c (md_pseudo_table): Change "octa" and "quad" to
+       call pa_cons, not pa_big_cons.
+       (pa_big_cons): Remove.
+       * config/tc-hppa.h (pa_big_cons): Remove declaration.
+       * config/tc-i960.c (md_pseudo_table): Change "quad" to call cons,
+       not big_cons.
+
+Tue Oct  5 10:53:36 1993  david d `zoo' zuhn  (zoo@rtl.cygnus.com)
+
+       * doc/as.texinfo (Copying): new node, to handle the recent changes
+       in the texinfo/gpl.texinfo file
+
 Mon Oct  4 17:10:15 1993  Ian Lance Taylor  (ian@tweedledumb.cygnus.com)
 
        * read.c (big_cons): Handle "0" correctly.
index f58163f6351883c7ec6f599f299a80fbc25e3b4f..021043603f334916d24226cf67cd99076e9ca535 100644 (file)
@@ -421,6 +421,7 @@ parse_reglist (src, op)
   op->exp.X_op_symbol = 0;
   op->exp.X_add_number = mask;
   op->exp.X_op = O_constant;
+  op->exp.X_unsigned = 1;
   op->type = IMM8;
   return idx;
 
index 665606c9daee7fd9ac847ba540ee3525bc59f39a..f48a352c1005de5ce606eac3be7324968e1520b2 100644 (file)
@@ -233,8 +233,8 @@ const pseudo_typeS
   {"LONG", pa_cons, 4},
   {"lsym", pa_lsym, 0},
   {"LSYM", pa_lsym, 0},
-  {"octa", pa_big_cons, 16},
-  {"OCTA", pa_big_cons, 16},
+  {"octa", pa_cons, 16},
+  {"OCTA", pa_cons, 16},
   {"org", pa_origin, 0},
   {"ORG", pa_origin, 0},
   {"origin", pa_origin, 0},
@@ -245,8 +245,8 @@ const pseudo_typeS
   {"PROC", pa_proc, 0},
   {"procend", pa_procend, 0},
   {"PROCEND", pa_procend, 0},
-  {"quad", pa_big_cons, 8},
-  {"QUAD", pa_big_cons, 8},
+  {"quad", pa_cons, 8},
+  {"QUAD", pa_cons, 8},
   {"reg", pa_equ, 1},          /* very similar to .equ */
   {"REG", pa_equ, 1},          /* very similar to .equ */
   {"short", pa_cons, 2},
@@ -732,7 +732,7 @@ md_begin ()
     {
       const char *name = pa_opcodes[i].name;
       retval = hash_insert (op_hash, name, &pa_opcodes[i]);
-      if (retval != NULL && *retval != '\0')
+      if (retval != NULL)
        {
          as_fatal ("Internal error: can't hash `%s': %s\n",
                    pa_opcodes[i].name, retval);
@@ -4291,13 +4291,13 @@ s_seg ()
   if (strncmp (input_line_pointer, "\"text\"", 6) == 0)
     {
       input_line_pointer += 6;
-      s_text ();
+      s_text (0);
       return;
     }
   if (strncmp (input_line_pointer, "\"data\"", 6) == 0)
     {
       input_line_pointer += 6;
-      s_data ();
+      s_data (0);
       return;
     }
   if (strncmp (input_line_pointer, "\"data1\"", 7) == 0)
@@ -4317,22 +4317,14 @@ s_private ()
   register int temp;
 
   temp = get_absolute_expression ();
-#ifdef OBJ_SOM
-  subseg_new (SEG_DATA, (subsegT) temp);
-#else
-  subseg_new (".data", (subsegT) temp);
-#endif
+  subseg_set (data_section, (subsegT) temp);
   demand_empty_rest_of_line ();
 }
 
 void 
 s_data1 ()
 {
-#ifdef OBJ_SOM
-  subseg_new (SEG_DATA, 1);
-#else
-  subseg_new (".data", 1);
-#endif
+  subseg_set (data_section, 1);
   demand_empty_rest_of_line ();
   return;
 }
@@ -4498,7 +4490,7 @@ pa_build_unwind_subspace (call_info)
 
   save_seg = now_seg;
   save_subseg = now_subseg;
-  subseg_new ((char *) seg->name, subseg);
+  subseg_set (seg, subseg);
   unwindP = (char *) &call_info->ci_unwind;
 
   p = frag_more (4);
@@ -4567,7 +4559,7 @@ pa_build_unwind_subspace (call_info)
       }
     }
 
-  subseg_new ((char *) save_seg->name, save_subseg);
+  subseg_set (save_seg, save_subseg);
 }
 
 #else
@@ -4625,7 +4617,7 @@ pa_build_unwind_subspace (call_info)
 
   save_seg = now_seg;
   save_subseg = now_subseg;
-  subseg_new (seg, subseg);
+  subseg_set (seg, subseg);
   unwindP = (char *) &call_info->ci_unwind;
 
   p = frag_more (4);
@@ -4710,7 +4702,7 @@ pa_build_unwind_subspace (call_info)
       }
     }
 
-  subseg_new (save_seg, save_subseg);
+  subseg_set (save_seg, save_subseg);
 
 }
 
@@ -4834,13 +4826,8 @@ pa_code ()
     }
 
   SPACE_DEFINED (sdchain) = 1;
-#ifdef OBJ_SOM
 
-  subseg_new (SEG_TEXT, SUBSEG_CODE);
-#else
-
-  subseg_new (".text", SUBSEG_CODE);
-#endif
+  subseg_set (text_section, SUBSEG_CODE);
 
   demand_empty_rest_of_line ();
   return;
@@ -5210,7 +5197,7 @@ void
                         seg,
                         SEC_HAS_CONTENTS | SEC_READONLY | SEC_ALLOC | SEC_LOAD);
 
-  subseg_new(save_seg->name, save_subseg);
+  subseg_set(save_seg, save_subseg);
   
 }
 #endif
@@ -5520,7 +5507,7 @@ pa_leave ()
 void 
 pa_origin ()
 {
-  s_org ();                    /* ORG actually allows another argument
+  s_org (0);                   /* ORG actually allows another argument
                                   (the fill value) but maybe this is OK? */
   pa_undefine_label ();
   return;
@@ -5787,11 +5774,7 @@ pa_parse_space_stmt (space_name, create_flag)
 
 void 
 pa_align_subseg (seg, subseg)
-#ifdef OBJ_SOM
      segT seg;
-#else
-     asection *seg;
-#endif
      subsegT subseg;
 {
   subspace_dict_chainS *now_subspace;
@@ -5841,22 +5824,12 @@ pa_space ()
          current_space = sd_chain;
          SPACE_DEFINED (current_space) = 1;
          current_space->sd_defined = 1;
-#ifdef OBJ_SOM
-         if (now_seg != SEG_TEXT)      /* no need to align if we are already there */
-#else
          if (now_seg != text_section)  /* no need to align if we are already there */
-#endif
            pa_align_subseg (now_seg, now_subseg);
 
-#ifdef OBJ_SOM
-         subseg_new (SEG_TEXT, sd_chain->sd_last_subseg);
-         current_subspace = pa_subsegment_to_subspace (SEG_TEXT,
-                                                 sd_chain->sd_last_subseg);
-#else
-         subseg_new ((char *) text_section->name, sd_chain->sd_last_subseg);
+         subseg_set (text_section, sd_chain->sd_last_subseg);
          current_subspace = pa_subsegment_to_subspace (text_section,
                                                  sd_chain->sd_last_subseg);
-#endif
          demand_empty_rest_of_line ();
          return;
        }
@@ -5872,21 +5845,11 @@ pa_space ()
          current_space = sd_chain;
          SPACE_DEFINED (current_space) = 1;
          current_space->sd_defined = 1;
-#ifdef OBJ_SOM
-         if (now_seg != SEG_DATA)      /* no need to align if we are already there */
-#else
          if (now_seg != data_section)  /* no need to align if we are already there */
-#endif
            pa_align_subseg (now_seg, now_subseg);
-#ifdef OBJ_SOM
-         subseg_new (SEG_DATA, sd_chain->sd_last_subseg);
-         current_subspace = pa_subsegment_to_subspace (SEG_DATA,
-                                                 sd_chain->sd_last_subseg);
-#else
-         subseg_new ((char *) data_section->name, sd_chain->sd_last_subseg);
+         subseg_set (data_section, sd_chain->sd_last_subseg);
          current_subspace = pa_subsegment_to_subspace (data_section,
                                                  sd_chain->sd_last_subseg);
-#endif
          demand_empty_rest_of_line ();
          return;
        }
@@ -5903,19 +5866,22 @@ pa_space ()
          current_space = sd_chain;
          SPACE_DEFINED (current_space) = 1;
          current_space->sd_defined = 1;
+
 #ifdef OBJ_SOM
-         if (now_seg != SEG_GDB)       /* no need to align if we are already there */
+         if (now_seg != SEG_GDB)  /* no need to align if we are already there */
+
            pa_align_subseg (now_seg, now_subseg);
-         subseg_new (SEG_GDB, sd_chain->sd_last_subseg);
+         subseg_set (SEG_GDB, sd_chain->sd_last_subseg);
          current_subspace = pa_subsegment_to_subspace (SEG_GDB,
                                                  sd_chain->sd_last_subseg);
 #else
          {
-           asection *gdb_section
-             = bfd_make_section_old_way (stdoutput, GDB_DEBUG_SPACE_NAME);
-           if (now_seg != gdb_section) /* no need to align if we are already there */
+           segT gdb_section;
+           /* no need to align if we are already there */
+           if (strcmp (segment_name (now_seg), GDB_DEBUG_SPACE_NAME) != 0)
              pa_align_subseg (now_seg, now_subseg);
-           subseg_new ((char *) gdb_section->name, sd_chain->sd_last_subseg);
+           gdb_section = subseg_new (GDB_DEBUG_SPACE_NAME,
+                                     sd_chain->sd_last_subseg);
            current_subspace = pa_subsegment_to_subspace (gdb_section,
                                                          sd_chain->sd_last_subseg);
          }
@@ -5935,11 +5901,7 @@ pa_space ()
              current_space->sd_defined = 1;
              if (now_seg != sd_chain->sd_seg)  /* don't align if we're already there */
                pa_align_subseg (now_seg, now_subseg);
-#ifdef OBJ_SOM
-             subseg_new (sd_chain->sd_seg, sd_chain->sd_last_subseg);
-#else
-             subseg_new ((char *) sd_chain->sd_seg->name, sd_chain->sd_last_subseg);
-#endif
+             subseg_set (sd_chain->sd_seg, sd_chain->sd_last_subseg);
              current_subspace = pa_subsegment_to_subspace (sd_chain->sd_seg,
                                                  sd_chain->sd_last_subseg);
              demand_empty_rest_of_line ();
@@ -5961,11 +5923,7 @@ pa_space ()
       current_space->sd_defined = 1;
       if (now_seg != sd_chain->sd_seg) /* don't align if we're already there */
        pa_align_subseg (now_seg, now_subseg);
-#ifdef OBJ_SOM
-      subseg_new (sd_chain->sd_seg, sd_chain->sd_last_subseg);
-#else
-      subseg_new ((char *) sd_chain->sd_seg->name, sd_chain->sd_last_subseg);
-#endif
+      subseg_set (sd_chain->sd_seg, sd_chain->sd_last_subseg);
       current_subspace = pa_subsegment_to_subspace (sd_chain->sd_seg,
                                                  sd_chain->sd_last_subseg);
       demand_empty_rest_of_line ();
@@ -6068,7 +6026,7 @@ pa_subspace ()
          if (ssd->ssd_defined)
            {
 #ifdef OBJ_SOM
-             subseg_new (now_seg, ssd->ssd_subseg);
+             subseg_set (now_seg, ssd->ssd_subseg);
 #else
              /* subseg_new(now_seg->name,ssd->ssd_subseg); */
              subseg_new ((char *) ssd->ssd_seg->name, ssd->ssd_subseg);
@@ -6202,11 +6160,7 @@ pa_subspace ()
       SUBSPACE_SUBSPACE_START (current_subspace) = pa_subspace_start (space, quadrant);
 
       demand_empty_rest_of_line ();
-#ifdef OBJ_SOM
-      subseg_new (current_subspace->ssd_seg, current_subspace->ssd_subseg);
-#else
-      subseg_new ((char *) current_subspace->ssd_seg->name, current_subspace->ssd_subseg);
-#endif
+      subseg_set (current_subspace->ssd_seg, current_subspace->ssd_subseg);
     }
   return;
 }
@@ -6887,7 +6841,7 @@ pa_cons (nbytes)
 void
 pa_data ()
 {
-  s_data ();
+  s_data (0);
   pa_undefine_label ();
 }
 
@@ -6912,7 +6866,7 @@ pa_float_cons (float_type)
 void
 pa_fill ()
 {
-  s_fill ();
+  s_fill (0);
   pa_undefine_label ();
 }
 
@@ -6929,22 +6883,14 @@ pa_lcomm (needs_align)
 void
 pa_lsym ()
 {
-  s_lsym ();
-  pa_undefine_label ();
-}
-
-void
-pa_big_cons (nbytes)
-     register int nbytes;
-{
-  big_cons (nbytes);
+  s_lsym (0);
   pa_undefine_label ();
 }
 
 void
 pa_text ()
 {
-  s_text ();
+  s_text (0);
   pa_undefine_label ();
 }
 
@@ -7043,7 +6989,7 @@ bfd * abfd;
 
   /* now, switch back to the original segment */
 
-  subseg_new(save_seg->name, save_subseg);
+  subseg_set(save_seg, save_subseg);
 
   return;
 }
@@ -7073,6 +7019,6 @@ hppa_tc_make_symextn_section()
       bfd_set_section_size (stdoutput, symextn_sec, size);
 
       /* now, switch back to the original segment */
-      subseg_new(save_seg->name, save_subseg);
+      subseg_set(save_seg, save_subseg);
     }
 }
index be54da49bced51df3bfa0f042e82e1138a7c97b5..4c045be4b54f8927e3938401b4c8960f802306da 100644 (file)
@@ -201,7 +201,7 @@ const pseudo_typeS md_pseudo_table[] =
   {"sysproc", parse_po, S_SYSPROC},
 
   {"word", cons, 4},
-  {"quad", big_cons, 16},
+  {"quad", cons, 16},
 
   {0, 0, 0}
 };
@@ -508,41 +508,31 @@ md_begin ()
 {
   int i;                       /* Loop counter */
   const struct i960_opcode *oP;        /* Pointer into opcode table */
-  char *retval;                        /* Value returned by hash functions */
+  const char *retval;          /* Value returned by hash functions */
 
   if (((op_hash = hash_new ()) == 0)
       || ((reg_hash = hash_new ()) == 0)
       || ((areg_hash = hash_new ()) == 0))
-    {
-      as_fatal ("virtual memory exceeded");
-    }
+    as_fatal ("virtual memory exceeded");
 
   /* For some reason, the base assembler uses an empty string for "no
      error message", instead of a NULL pointer.  */
   retval = "";
 
-  for (oP = i960_opcodes; oP->name && !*retval; oP++)
-    {
-      retval = hash_insert (op_hash, oP->name, oP);
-    }
+  for (oP = i960_opcodes; oP->name && !retval; oP++)
+    retval = hash_insert (op_hash, oP->name, (PTR) oP);
 
-  for (i = 0; regnames[i].reg_name && !*retval; i++)
-    {
-      retval = hash_insert (reg_hash, regnames[i].reg_name,
-                           &regnames[i].reg_num);
-    }
+  for (i = 0; regnames[i].reg_name && !retval; i++)
+    retval = hash_insert (reg_hash, regnames[i].reg_name,
+                         &regnames[i].reg_num);
 
-  for (i = 0; aregs[i].areg_name && !*retval; i++)
-    {
-      retval = hash_insert (areg_hash, aregs[i].areg_name,
-                           &aregs[i].areg_num);
-    }
+  for (i = 0; aregs[i].areg_name && !retval; i++)
+    retval = hash_insert (areg_hash, aregs[i].areg_name,
+                         &aregs[i].areg_num);
 
-  if (*retval)
-    {
-      as_fatal ("Hashing returned \"%s\".", retval);
-    }
-}                              /* md_begin() */
+  if (retval)
+    as_fatal ("Hashing returned \"%s\".", retval);
+}
 
 /*****************************************************************************
  * md_end:  One-time final cleanup
@@ -577,7 +567,6 @@ md_assemble (textP)
   char *args[4];
 
   int n_ops;                   /* Number of instruction operands */
-  int callx;
   /* Pointer to instruction description */
   struct i960_opcode *oP;
   /* TRUE iff opcode mnemonic included branch-prediction
@@ -896,7 +885,7 @@ md_number_to_field (instrP, val, bfixP)
   if (((val < 0) && (sign != -1))
       || ((val > 0) && (sign != 0)))
     {
-      as_bad ("Fixup of %d too large for field width of %d",
+      as_bad ("Fixup of %ld too large for field width of %d",
              val, numbits);
     }
   else
@@ -964,14 +953,14 @@ md_parse_option (argP, cntP, vecP)
     };
   static struct tabentry arch_tab[] =
   {
-    "KA", ARCH_KA,
-    "KB", ARCH_KB,
-    "SA", ARCH_KA,             /* Synonym for KA */
-    "SB", ARCH_KB,             /* Synonym for KB */
-    "KC", ARCH_MC,             /* Synonym for MC */
-    "MC", ARCH_MC,
-    "CA", ARCH_CA,
-    NULL, 0
+    { "KA", ARCH_KA },
+    { "KB", ARCH_KB },
+    { "SA", ARCH_KA },         /* Synonym for KA */
+    { "SB", ARCH_KB },         /* Synonym for KB */
+    { "KC", ARCH_MC },         /* Synonym for MC */
+    { "MC", ARCH_MC },
+    { "CA", ARCH_CA },
+    { NULL, 0 }
   };
   struct tabentry *tp;
   if (!strcmp (*argP, "linkrelax"))
@@ -2220,7 +2209,7 @@ parse_po (po_num)
 
   /* Advance input pointer to end of line. */
   p = input_line_pointer;
-  while (!is_end_of_line[*input_line_pointer])
+  while (!is_end_of_line[(unsigned char) *input_line_pointer])
     {
       input_line_pointer++;
     }
@@ -2458,22 +2447,22 @@ struct
 
 coj[] =
 {                              /* COBR OPCODE: */
-  CHKBIT, BNO,                 /*      0x30 - bbc */
-  CMPO, BG,                    /*      0x31 - cmpobg */
-  CMPO, BE,                    /*      0x32 - cmpobe */
-  CMPO, BGE,                   /*      0x33 - cmpobge */
-  CMPO, BL,                    /*      0x34 - cmpobl */
-  CMPO, BNE,                   /*      0x35 - cmpobne */
-  CMPO, BLE,                   /*      0x36 - cmpoble */
-  CHKBIT, BO,                  /*      0x37 - bbs */
-  CMPI, BNO,                   /*      0x38 - cmpibno */
-  CMPI, BG,                    /*      0x39 - cmpibg */
-  CMPI, BE,                    /*      0x3a - cmpibe */
-  CMPI, BGE,                   /*      0x3b - cmpibge */
-  CMPI, BL,                    /*      0x3c - cmpibl */
-  CMPI, BNE,                   /*      0x3d - cmpibne */
-  CMPI, BLE,                   /*      0x3e - cmpible */
-  CMPI, BO,                    /*      0x3f - cmpibo */
+  { CHKBIT, BNO },             /*      0x30 - bbc */
+  { CMPO, BG },                        /*      0x31 - cmpobg */
+  { CMPO, BE },                        /*      0x32 - cmpobe */
+  { CMPO, BGE },               /*      0x33 - cmpobge */
+  { CMPO, BL },                        /*      0x34 - cmpobl */
+  { CMPO, BNE },               /*      0x35 - cmpobne */
+  { CMPO, BLE },               /*      0x36 - cmpoble */
+  { CHKBIT, BO },              /*      0x37 - bbs */
+  { CMPI, BNO },               /*      0x38 - cmpibno */
+  { CMPI, BG },                        /*      0x39 - cmpibg */
+  { CMPI, BE },                        /*      0x3a - cmpibe */
+  { CMPI, BGE },               /*      0x3b - cmpibge */
+  { CMPI, BL },                        /*      0x3c - cmpibl */
+  { CMPI, BNE },               /*      0x3d - cmpibne */
+  { CMPI, BLE },               /*      0x3e - cmpible */
+  { CMPI, BO },                        /*      0x3f - cmpibo */
 };
 
 static
@@ -3174,10 +3163,6 @@ i960_handle_align (fragp)
      fragS *fragp;
 {
   fixS *fixp;
-  segT old_seg = now_seg, this_seg;
-  int old_subseg = now_subseg;
-  int pad_size;
-  extern struct frag *text_last_frag, *data_last_frag;
 
   if (!linkrelax)
     return;
index 762d3d8fb95e27fb263eb7eef0d8b099da479451..f741f465d74abfdcf2888235fa0419d7d364a101 100644 (file)
@@ -133,12 +133,6 @@ char is_end_of_line[256] =
 static char *buffer;   /* 1st char of each buffer of lines is here. */
 static char *buffer_limit;     /*->1 + last char in buffer. */
 
-static char *bignum_low;       /* Lowest char of bignum. */
-static char *bignum_limit;     /* 1st illegal address of bignum. */
-static char *bignum_high;      /* Highest char of bignum. */
-/* May point to (bignum_start-1). */
-/* Never >= bignum_limit. */
-
 int target_big_endian;
 
 static char *old_buffer;       /* JF a hack */
@@ -161,10 +155,7 @@ static char *demand_copy_string PARAMS ((int *lenP));
 int is_it_end_of_statement PARAMS ((void));
 static segT get_segmented_expression PARAMS ((expressionS *expP));
 static segT get_known_segmented_expression PARAMS ((expressionS * expP));
-static void grow_bignum PARAMS ((void));
 static void pobegin PARAMS ((void));
-
-extern int listing;
 \f
 
 void
@@ -180,10 +171,6 @@ read_begin ()
   obstack_begin (&notes, 5090);
   obstack_begin (&cond_obstack, 990);
 
-#define BIGNUM_BEGIN_SIZE (16)
-  bignum_low = xmalloc ((long) BIGNUM_BEGIN_SIZE);
-  bignum_limit = bignum_low + BIGNUM_BEGIN_SIZE;
-
   /* Use machine dependent syntax */
   for (p = line_separator_chars; *p; p++)
     is_end_of_line[(unsigned char) *p] = 1;
@@ -241,11 +228,11 @@ static const pseudo_typeS potable[] =
   {"long", cons, 4},
   {"lsym", s_lsym, 0},
   {"nolist", listing_list, 0}, /* Turn listing off */
-  {"octa", big_cons, 16},
+  {"octa", cons, 16},
   {"org", s_org, 0},
   {"psize", listing_psize, 0}, /* set paper size */
 /* print */
-  {"quad", big_cons, 8},
+  {"quad", cons, 8},
   {"sbttl", listing_title, 1}, /* Subtitle of listing */
 /* scl */
 /* sect */
@@ -281,7 +268,7 @@ pobegin ()
   for (pop = md_pseudo_table; pop->poc_name; pop++)
     {
       errtxt = hash_insert (po_hash, pop->poc_name, (char *) pop);
-      if (errtxt && *errtxt)
+      if (errtxt)
        {
          as_fatal ("error constructing md pseudo-op table");
        }                       /* on error */
@@ -291,7 +278,7 @@ pobegin ()
   for (pop = obj_pseudo_table; pop->poc_name; pop++)
     {
       errtxt = hash_insert (po_hash, pop->poc_name, (char *) pop);
-      if (errtxt && *errtxt)
+      if (errtxt)
        {
          if (!strcmp (errtxt, "exists"))
            {
@@ -311,7 +298,7 @@ pobegin ()
   for (pop = potable; pop->poc_name; pop++)
     {
       errtxt = hash_insert (po_hash, pop->poc_name, (char *) pop);
-      if (errtxt && *errtxt)
+      if (errtxt)
        {
          if (!strcmp (errtxt, "exists"))
            {
@@ -1529,7 +1516,7 @@ pseudo_set (symbolP)
  *
  * CONStruct more frag of .bytes, or .words etc.
  * Should need_pass_2 be 1 then emit no frag(s).
- * This understands EXPRESSIONS, as opposed to big_cons().
+ * This understands EXPRESSIONS.
  *
  * Bug (?)
  *
@@ -1608,6 +1595,7 @@ emit_expr (exp, nbytes)
 {
   operatorT op;
   register char *p;
+  valueT extra_digit = 0;
 
   /* Don't do anything if we are going to make another pass.  */
   if (need_pass_2)
@@ -1615,16 +1603,46 @@ emit_expr (exp, nbytes)
 
   op = exp->X_op;
 
+  /* Handle a negative bignum.  */
+  if (op == O_uminus
+      && exp->X_add_number == 0
+      && exp->X_add_symbol->sy_value.X_op == O_big
+      && exp->X_add_symbol->sy_value.X_add_number > 0)
+    {
+      int i;
+      unsigned long carry;
+
+      exp = &exp->X_add_symbol->sy_value;
+
+      /* Negate the bignum: one's complement each digit and add 1.  */
+      carry = 1;
+      for (i = 0; i < exp->X_add_number; i++)
+       {
+         unsigned long next;
+
+         next = (((~ (generic_bignum[i] & LITTLENUM_MASK))
+                  & LITTLENUM_MASK)
+                 + carry);
+         generic_bignum[i] = next & LITTLENUM_MASK;
+         carry = next >> LITTLENUM_NUMBER_OF_BITS;
+       }
+
+      /* We can ignore any carry out, because it will be handled by
+        extra_digit if it is needed.  */
+
+      extra_digit = (valueT) -1;
+      op = O_big;
+    }
+
   if (op == O_absent || op == O_illegal)
     {
       as_warn ("zero assumed for missing expression");
       exp->X_add_number = 0;
       op = O_constant;
     }
-  else if (op == O_big)
+  else if (op == O_big && exp->X_add_number <= 0)
     {
-      as_bad ("%s number invalid; zero assumed",
-             exp->X_add_number > 0 ? "bignum" : "floating point");
+      as_bad ("floating point number invalid; zero assumed");
       exp->X_add_number = 0;
       op = O_constant;
     }
@@ -1658,6 +1676,28 @@ emit_expr (exp, nbytes)
     }
 #endif
 
+  /* If we have an integer, but the number of bytes is too large to
+     pass to md_number_to_chars, handle it as a bignum.  */
+  if (op == O_constant && nbytes > sizeof (valueT))
+    {
+      valueT val;
+      int gencnt;
+
+      if (! exp->X_unsigned && exp->X_add_number < 0)
+       extra_digit = (valueT) -1;
+      val = (valueT) exp->X_add_number;
+      gencnt = 0;
+      do
+       {
+         generic_bignum[gencnt] = val & LITTLENUM_MASK;
+         val >>= LITTLENUM_NUMBER_OF_BITS;
+         ++gencnt;
+       }
+      while (val != 0);
+      op = exp->X_op = O_big;
+      exp->X_add_number = gencnt;
+    }
+
   if (op == O_constant)
     {
       register long get;
@@ -1688,6 +1728,58 @@ emit_expr (exp, nbytes)
       /* put bytes in right order. */
       md_number_to_chars (p, (valueT) use, (int) nbytes);
     }
+  else if (op == O_big)
+    {
+      int size;
+      LITTLENUM_TYPE *nums;
+
+      know (nbytes % CHARS_PER_LITTLENUM == 0);
+
+      size = exp->X_add_number * CHARS_PER_LITTLENUM;
+      if (nbytes < size)
+       {
+         as_warn ("Bignum truncated to %d bytes", nbytes);
+         size = nbytes;
+       }
+
+      if (target_big_endian)
+       {
+         while (nbytes > size)
+           {
+             md_number_to_chars (p, extra_digit, CHARS_PER_LITTLENUM);
+             nbytes -= CHARS_PER_LITTLENUM;
+             p += CHARS_PER_LITTLENUM;
+           }
+
+         nums = generic_bignum + size / CHARS_PER_LITTLENUM;
+         while (size > 0)
+           {
+             --nums;
+             md_number_to_chars (p, (valueT) *nums, CHARS_PER_LITTLENUM);
+             size -= CHARS_PER_LITTLENUM;
+             p += CHARS_PER_LITTLENUM;
+           }
+       }
+      else
+       {
+         nums = generic_bignum;
+         while (size > 0)
+           {
+             md_number_to_chars (p, (valueT) *nums, CHARS_PER_LITTLENUM);
+             ++nums;
+             size -= CHARS_PER_LITTLENUM;
+             p += CHARS_PER_LITTLENUM;
+             nbytes -= CHARS_PER_LITTLENUM;
+           }
+
+         while (nbytes > 0)
+           {
+             md_number_to_chars (p, extra_digit, CHARS_PER_LITTLENUM);
+             nbytes -= CHARS_PER_LITTLENUM;
+             p += CHARS_PER_LITTLENUM;
+           }
+       }
+    }
   else
     {
       md_number_to_chars (p, (valueT) 0, (int) nbytes);
@@ -1725,7 +1817,7 @@ emit_expr (exp, nbytes)
 #define TC_CONS_RELOC 0
 #endif
 #endif
-      fix_new_exp (frag_now, p - frag_now->fr_literal, nbytes, exp, 0,
+      fix_new_exp (frag_now, p - frag_now->fr_literal, (int) nbytes, exp, 0,
                   TC_CONS_RELOC);
 #endif /* TC_CONS_FIX_NEW */
 #endif /* BFD_ASSEMBLER */
@@ -1808,7 +1900,7 @@ parse_bitfield_cons (exp, nbytes)
 
          if ((width = exp->X_add_number) > (BITS_PER_CHAR * nbytes))
            {
-             as_warn ("field width %d too big to fit in %d bytes: truncated to %d bits",
+             as_warn ("field width %lu too big to fit in %d bytes: truncated to %d bits",
                       width, nbytes, (BITS_PER_CHAR * nbytes));
              width = BITS_PER_CHAR * nbytes;
            }                   /* too big */
@@ -1851,6 +1943,7 @@ parse_bitfield_cons (exp, nbytes)
 
       exp->X_add_number = value;
       exp->X_op = O_constant;
+      exp->X_unsigned = 1;
     }                          /* if looks like a bitfield */
 }                              /* parse_bitfield_cons() */
 
@@ -1952,164 +2045,6 @@ parse_repeat_cons (exp, nbytes)
 
 #endif /* REPEAT_CONS_EXPRESSIONS */
 \f
-/*
- *                     big_cons()
- *
- * CONStruct more frag(s) of .quads, or .octa etc.
- * Makes 0 or more new frags.
- * If need_pass_2 == 1, generate no frag.
- * This understands only bignums, not expressions. Cons() understands
- * expressions.
- *
- * Constants recognised are '0...'(octal) '0x...'(hex) '...'(decimal).
- *
- * This creates objects with struct obstack_control objs, destroying
- * any context objs held about a partially completed object. Beware!
- *
- *
- * I think it sucks to have 2 different types of integers, with 2
- * routines to read them, store them etc.
- * It would be nicer to permit bignums in expressions and only
- * complain if the result overflowed. However, due to "efficiency"...
- */
-/* Worker to do .quad etc statements.  Clobbers input_line_pointer, checks
-   end-of-line.  8=.quad 16=.octa ... */
-
-void 
-big_cons (nbytes)
-     register int nbytes;
-{
-  register char c;             /* input_line_pointer->c. */
-  register int radix;
-  register long length;                /* Number of chars in an object. */
-  register int digit;          /* Value of 1 digit. */
-  register int carry;          /* For multi-precision arithmetic. */
-  register int work;           /* For multi-precision arithmetic. */
-  register char *p;            /* For multi-precision arithmetic. */
-
-  extern const char hex_value[];       /* In hex_value.c. */
-
-  /*
-   * The following awkward logic is to parse ZERO or more strings,
-   * comma seperated. Recall an expression includes its leading &
-   * trailing blanks. We fake a leading ',' if there is (supposed to
-   * be) a 1st expression, and keep demanding 1 expression for each ','.
-   */
-  if (is_it_end_of_statement ())
-    {
-      c = 0;                   /* Skip loop. */
-    }
-  else
-    {
-      c = ',';                 /* Do loop. */
-      --input_line_pointer;
-    }
-  while (c == ',')
-    {
-      ++input_line_pointer;
-      SKIP_WHITESPACE ();
-      c = *input_line_pointer;
-      /* C contains 1st non-blank character of what we hope is a number. */
-      if (c == '0')
-       {
-         c = *++input_line_pointer;
-         if (c == 'x' || c == 'X')
-           {
-             c = *++input_line_pointer;
-             radix = 16;
-           }
-         else
-           {
-             radix = 8;
-           }
-       }
-      else
-       {
-         radix = 10;
-       }
-      /*
-       * This feature (?) is here to stop people worrying about
-       * mysterious zero constants: which is what they get when
-       * they completely omit digits.
-       */
-      if (hex_value[(unsigned char) c] >= radix)
-       {
-         as_bad ("Missing digits. 0 assumed.");
-       }
-      bignum_high = bignum_low - 1;    /* Start constant with 0 chars. */
-      for (;
-          (digit = hex_value[(unsigned char) c]) < radix;
-          c = *++input_line_pointer)
-       {
-         /* Multiply existing number by radix, then add digit. */
-         carry = digit;
-         for (p = bignum_low; p <= bignum_high; p++)
-           {
-             work = (*p & MASK_CHAR) * radix + carry;
-             *p = work & MASK_CHAR;
-             carry = work >> BITS_PER_CHAR;
-           }
-         if (carry)
-           {
-             grow_bignum ();
-             *bignum_high = carry & MASK_CHAR;
-             know ((carry & ~MASK_CHAR) == 0);
-           }
-       }
-      length = bignum_high - bignum_low + 1;
-      if (length > nbytes)
-       {
-         as_warn ("Most significant bits truncated in integer constant.");
-       }
-      else
-       {
-         register long leading_zeroes;
-
-         for (leading_zeroes = nbytes - length;
-              leading_zeroes;
-              leading_zeroes--)
-           {
-             grow_bignum ();
-             *bignum_high = 0;
-           }
-       }
-      if (!need_pass_2)
-       {
-         char *src = bignum_low;
-         p = frag_more (nbytes);
-         if (target_big_endian)
-           {
-             int i;
-             for (i = nbytes - 1; i >= 0; i--)
-               p[i] = *src++;
-           }
-         else
-           memcpy (p, bignum_low, (unsigned int) nbytes);
-       }
-      /* C contains character after number. */
-      SKIP_WHITESPACE ();
-      c = *input_line_pointer;
-      /* C contains 1st non-blank character after number. */
-    }
-  demand_empty_rest_of_line ();
-}                              /* big_cons() */
-
-/* Extend bignum by 1 char. */
-static void 
-grow_bignum ()
-{
-  register unsigned long length;
-
-  bignum_high++;
-  if (bignum_high >= bignum_limit)
-    {
-      length = bignum_limit - bignum_low;
-      bignum_low = xrealloc (bignum_low, length + length);
-      bignum_high = bignum_low + length;
-      bignum_limit = bignum_low + length + length;
-    }
-}                              /* grow_bignum(); */
-\f
 /*
  *                     float_cons()
  *
@@ -2162,7 +2097,7 @@ float_cons (float_type)
       err = md_atof (float_type, temp, &length);
       know (length <= MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT);
       know (length > 0);
-      if (err && *err)
+      if (err)
        {
          as_bad ("Bad floating literal: %s", err);
          ignore_rest_of_line ();
@@ -2639,7 +2574,7 @@ s_ignore (arg)
 
   return;
 }                              /* s_ignore() */
-
+\f
 /*
  * Handle .stabX directives, which used to be open-coded.
  * So much creeping featurism overloaded the semantics that we decided
@@ -2655,34 +2590,6 @@ s_ignore (arg)
  * don't need and invent information they need that you didn't supply.
  */
 
-void
-change_to_section (name, len, exp)
-       char *name;
-       unsigned int len;
-       unsigned int exp;
-{
-#ifndef BFD_ASSEMBLER
-#ifdef MANY_SEGMENTS
-  unsigned int i;
-  extern segment_info_type segment_info[];
-
-  /* Find out if we've already got a section of this name etc */
-  for (i = SEG_E0; i < SEG_E9 && segment_info[i].scnhdr.s_name[0]; i++)
-    {
-      if (strncmp (segment_info[i].scnhdr.s_name, name, len) == 0)
-       {
-         subseg_set (i, exp);
-         return;
-       }
-    }
-  /* No section, add one */
-  strncpy (segment_info[i].scnhdr.s_name, name, 8);
-  segment_info[i].scnhdr.s_flags = 0 /* STYP_NOLOAD */;
-  subseg_set (i, exp);
-#endif
-#endif
-}
-
 /*
  * Build a string dictionary entry for a .stabX symbol.
  * The symbol is added to the .<secname>str section.
@@ -2690,73 +2597,60 @@ change_to_section (name, len, exp)
 
 #ifdef SEPARATE_STAB_SECTIONS
 
-static unsigned int
+unsigned int
 get_stab_string_offset (string, secname)
-     char *string, *secname;
+     const char *string;
+     const char *secname;
 {
-  segT save_seg;
-  segT seg;
-  subsegT save_subseg;
   unsigned int length;
-  unsigned int old_gdb_string_index;
-  char *clengthP;
-  int i;
-  char c;
-  /* @@FIXME -- there should be no static data here!
-     This also has the effect of making all stab string tables large enough
-     to contain all the contents written to any of them.  This only matters
-     with the Solaris native compiler for the moment, but it should be fixed
-     anyways.  */
-  static unsigned int gdb_string_index = 0;
-
-  old_gdb_string_index = 0;
+  unsigned int retval;
+
+  retval = 0;
   length = strlen (string);
-  clengthP = (char *) &length;
   if (length > 0)
     {                          /* Ordinary case. */
+      segT save_seg;
+      subsegT save_subseg;
+      char *newsecname;
+      segT seg;
+      int aligned;
+      char *p;
+
       save_seg = now_seg;
       save_subseg = now_subseg;
 
-      /* Create the stabstr sections, if they are not already created. */
-      {
-       char *newsecname = xmalloc (strlen (secname) + 4);
-       strcpy (newsecname, secname);
-       strcat (newsecname, "str");
+      /* Create the stab string section.  */
+      newsecname = xmalloc ((unsigned long) (strlen (secname) + 4));
+      strcpy (newsecname, secname);
+      strcat (newsecname, "str");
+
+      seg = subseg_new (newsecname, 0);
+
+      retval = seg_info (seg)->stabu.stab_string_size;
+      if (retval > 0)
+       free (newsecname);
+      else
+       {
+         /* Make sure the first string is empty.  */
+         p = frag_more (1);
+         *p = 0;
+         retval = seg_info (seg)->stabu.stab_string_size = 1;
 #ifdef BFD_ASSEMBLER
-       seg = bfd_get_section_by_name (stdoutput, newsecname);
-       if (seg == 0)
-         {
-           seg = bfd_make_section_old_way (stdoutput, newsecname);
-           bfd_set_section_flags (stdoutput, seg, SEC_READONLY | SEC_ALLOC);
-         }
+         bfd_set_section_flags (stdoutput, seg, SEC_READONLY);
 #else
-       subseg_new (newsecname, 0);
+         free (newsecname);
 #endif
-/*     free (newsecname);*/
-      }
-      subseg_set (seg, save_subseg);
-      old_gdb_string_index = gdb_string_index;
-      i = 0;
-      while ((c = *string++))
-       {
-         i++;
-         gdb_string_index++;
-         FRAG_APPEND_1_CHAR (c);
-       }
-      {
-       FRAG_APPEND_1_CHAR ((char) 0);
-       i++;
-       gdb_string_index++;
-      }
-      while (i % 4 != 0)
-       {
-         FRAG_APPEND_1_CHAR ((char) 0);
-         i++;
-         gdb_string_index++;
        }
+
+      p = frag_more (length + 1);
+      strcpy (p, string);
+
+      seg_info (seg)->stabu.stab_string_size += length + 1;
+
       subseg_set (save_seg, save_subseg);
     }
-  return old_gdb_string_index;
+
+  return retval;
 }
 
 #endif /* SEPARATE_STAB_SECTIONS */
@@ -2769,227 +2663,187 @@ s_stab_generic (what, secname)
      int what;
      char *secname;
 {
-  extern int listing;
-
-  symbolS *symbol;
-  char *string;
-  int saved_type = 0;
-  int length;
-  int goof = 0;
   long longint;
-  segT saved_seg = now_seg;
-  segT seg;
-  subsegT saved_subseg = now_subseg;
-  subsegT subseg;
-  valueT valu;
-#ifdef SEPARATE_STAB_SECTIONS
-  int seg_is_new = 0;
-#endif
-
-  valu = ((char *) obstack_next_free (&frags)) - frag_now->fr_literal;
-
-#ifdef SEPARATE_STAB_SECTIONS
-#ifdef BFD_ASSEMBLER
-  seg = bfd_get_section_by_name (stdoutput, secname);
-  if (seg == 0)
+  char *string;
+  int type;
+  int other;
+  int desc;
+
+  /* The general format is:
+     .stabs "STRING",TYPE,OTHER,DESC,VALUE
+     .stabn TYPE,OTHER,DESC,VALUE
+     .stabd TYPE,OTHER,DESC
+     At this point input_line_pointer points after the pseudo-op and
+     any trailing whitespace.  The argument what is one of 's', 'n' or
+     'd' indicating which type of .stab this is.  */
+
+  if (what != 's')
+    string = "";
+  else
     {
-      seg = subseg_new (secname, 0);
-      bfd_set_section_flags (stdoutput, seg,
-                            SEC_READONLY | SEC_ALLOC | SEC_RELOC);
-      subseg_set (saved_seg, subseg);
-      seg_is_new = 1;
-    }
-#else
-  subseg_new (secname, 0);
-#endif
-#endif /* SEPARATE_STAB_SECTIONS */
+      int length;
 
-  /*
-   * Enter with input_line_pointer pointing past .stabX and any following
-   * whitespace.
-   */
-  if (what == 's')
-    {
       string = demand_copy_C_string (&length);
       SKIP_WHITESPACE ();
       if (*input_line_pointer == ',')
        input_line_pointer++;
       else
        {
-         as_bad ("I need a comma after symbol's name");
-         goof = 1;
+         as_warn (".stabs: Missing comma");
+         ignore_rest_of_line ();
+         return;
        }
     }
-  else
-    string = "";
 
-  /*
-   * Input_line_pointer->after ','.  String->symbol name.
-   */
-  if (!goof)
+  if (get_absolute_expression_and_terminator (&longint) != ',')
     {
-#ifdef MAKE_STAB_SYMBOL
-      MAKE_STAB_SYMBOL(symbol, string, secname);
-#else
-      symbol = symbol_new (string, undefined_section, 0, (struct frag *) 0);
-#endif
-      /* Make sure that the rest of this is going to work. */
-      if (symbol == NULL)
-       as_fatal ("no stab symbol created");
-
-      switch (what)
-       {
-       case 'd':
-         S_SET_NAME (symbol, NULL);    /* .stabd feature. */
-#ifdef STAB_SYMBOL_SET_VALUE
-         STAB_SYMBOL_SET_VALUE (symbol, valu);
-#else
-         S_SET_VALUE (symbol, valu);
-#endif
-#if STAB_SYMBOL_SET_SEGMENT
-#else
-         S_SET_SEGMENT (symbol, now_seg);
-#endif
-         symbol->sy_frag = frag_now;
-         break;
-
-       case 'n':
-         symbol->sy_frag = &zero_address_frag;
-         break;
-
-       case 's':
-         symbol->sy_frag = &zero_address_frag;
-         break;
-
-       default:
-         BAD_CASE (what);
-         break;
-       }
-
-      if (get_absolute_expression_and_terminator (&longint) == ',')
-       {
-         saved_type = longint;
-         S_SET_TYPE (symbol, saved_type);
-       }
-      else
-       {
-         as_bad ("I want a comma after the n_type expression");
-         goof = 1;
-         input_line_pointer--; /* Backup over a non-',' char. */
-       }
+      as_warn (".stab%c: Missing comma", what);
+      ignore_rest_of_line ();
+      return;
     }
+  type = longint;
 
-  if (!goof)
+  if (get_absolute_expression_and_terminator (&longint) != ',')
     {
-      if (get_absolute_expression_and_terminator (&longint) == ',')
-       S_SET_OTHER (symbol, longint);
-      else
-       {
-         as_bad ("I want a comma after the n_other expression");
-         goof = 1;
-         input_line_pointer--; /* Backup over a non-',' char. */
-       }
+      as_warn (".stab%c: Missing comma", what);
+      ignore_rest_of_line ();
+      return;
     }
+  other = longint;
 
-  if (!goof)
+  desc = get_absolute_expression ();
+  if (what == 's' || what == 'n')
     {
-      S_SET_DESC (symbol, get_absolute_expression ());
-      if (what == 's' || what == 'n')
+      if (*input_line_pointer != ',')
        {
-         if (*input_line_pointer != ',')
-           {
-             as_bad ("I want a comma after the n_desc expression");
-             goof = 1;
-           }
-         else
-           {
-             input_line_pointer++;
-           }
+         as_warn (".stab%c: Missing comma", what);
+         ignore_rest_of_line ();
+         return;
        }
+      input_line_pointer++;
+      SKIP_WHITESPACE ();
     }
 
-  /* Line is messed up - ignore it and get out of here. */
-  if (goof)
-    {
-      ignore_rest_of_line ();
-      subseg_set (saved_seg, saved_subseg);
-      return;
-    }
-
-  subseg_set (seg, subseg);
-
-#if 0  /* needed for elf only? */
-  if (seg_is_new)
-    /* allocate and discard -- filled in later */
-    (void) frag_more (12);
-#endif
+  /* We have not gathered the type, other, and desc information.  For
+     .stabs or .stabn, input_line_pointer is now pointing at the
+     value.  */
 
 #ifdef SEPARATE_STAB_SECTIONS
+  /* Output the stab information in a separate section.  This is used
+     at least for COFF and ELF.  */
   {
-    char *toP;
-
-    subseg_new (secname, 0);
-    toP = frag_more (8);
-    /* the string index portion of the stab */
-    md_number_to_chars (toP, (valueT) S_GET_OFFSET_2(symbol), 4);
-    md_number_to_chars (toP + 4, (valueT) S_GET_TYPE(symbol), 1);
-    md_number_to_chars (toP + 5, (valueT) S_GET_OTHER(symbol), 1);
-    md_number_to_chars (toP + 6, (valueT) S_GET_DESC(symbol), 2);
-  }
+    segT saved_seg = now_seg;
+    subsegT saved_subseg = now_subseg;
+    fragS *saved_frag = frag_now;
+    valueT dot;
+    segT seg;
+    unsigned int stroff;
+    char *p;
+    
+    dot = frag_now_fix ();
+
+    seg = subseg_new (secname, 0);
+
+    if (! seg_info (seg)->hadone)
+      {
+#ifdef BFD_ASSEMBLER
+       bfd_set_section_flags (stdoutput, seg, SEC_READONLY | SEC_RELOC);
+#endif
+#ifdef INIT_STAB_SECTION
+       INIT_STAB_SECTION (seg);
 #endif
+       seg_info (seg)->hadone = 1;
+      }
 
-#ifdef SEPARATE_STAB_SECTIONS
-  if (what == 's' || what == 'n')
-    {
-      cons (4);
-      input_line_pointer--;
-    }
-  else
-    {
-      char *p = frag_more (4);
-      md_number_to_chars (p, 0, 4);
-    }
-  subseg_set (saved_seg, subseg);
+    stroff = get_stab_string_offset (string, secname);
+
+    /* At least for now, stabs in a special stab section are always
+       output as 12 byte blocks of information.  */
+    p = frag_more (8);
+    md_number_to_chars (p, (valueT) stroff, 4);
+    md_number_to_chars (p + 4, (valueT) type, 1);
+    md_number_to_chars (p + 5, (valueT) other, 1);
+    md_number_to_chars (p + 6, (valueT) desc, 2);
+
+    if (what == 's' || what == 'n')
+      {
+       /* Pick up the value from the input line.  */
+       cons (4);
+       input_line_pointer--;
+      }
+    else
+      {
+       const char *fake;
+       symbolS *symbol;
+       expressionS exp;
+
+       /* Arrange for a value representing the current location.  */
+#ifdef DOT_LABEL_PREFIX
+       fake = ".L0\001";
 #else
-  if (what == 's' || what == 'n')
-    {
-      pseudo_set (symbol);
-      S_SET_TYPE (symbol, saved_type);
-    }
+       fake = "L0\001";
 #endif
+       symbol = symbol_new (fake, saved_seg, dot, saved_frag);
 
-#if 0  /* for elf only? */
-  if (what == 's' && S_GET_TYPE (symbol) == N_SO)
-    {
-      fragS *fragp = seg_info (seg)->frchainP->frch_root;
-      while (fragp
-            && fragp->fr_address + fragp->fr_fix < 12)
-       fragp = fragp->fr_next;
-      assert (fragp != 0);
-      assert (fragp->fr_type == rs_fill);
-      assert (fragp->fr_address == 0 && fragp->fr_fix >= 12);
-      md_number_to_chars (fragp->fr_literal, (valueT) symbol->sy_name_offset,
-                         4);
-    }
+       exp.X_op = O_symbol;
+       exp.X_add_symbol = symbol;
+       exp.X_add_number = 0;
+
+       emit_expr (&exp, 4);
+      }
+
+#ifdef OBJ_PROCESS_STAB
+    OBJ_PROCESS_STAB (seg, string, stroff, type, other, desc);
 #endif
 
-#ifndef NO_LISTING
-  if (listing)
-    switch (S_GET_TYPE (symbol))
+    subseg_set (saved_seg, saved_subseg);
+  }
+#else /* ! SEPARATE_STAB_SECTIONS */
+#ifdef OBJ_PROCESS_STAB
+  OBJ_PROCESS_STAB (what, string, type, other, desc);
+#else
+  /* Put the stab information in the symbol table.  */
+  {
+    symbolS *symbol;
+
+    symbol = symbol_new (string, undefined_section, 0,
+                        (struct frag *) NULL);
+    if (what == 's' || what == 'n')
+      {
+       /* Pick up the value from the input line.  */
+       symbol->sy_frag = &zero_address_frag;
+       pseudo_set (symbol);
+      }
+    else
       {
-      case N_SLINE:
-       listing_source_line ((unsigned int) S_GET_DESC (symbol));
-       break;
-      case N_SO:
-      case N_SOL:
-       listing_source_file (string);
-       break;
+       /* .stabd sets the name to NULL.  Why?  */
+       S_SET_NAME (symbol, NULL);
+       symbol->sy_frag = frag_now;
+       S_SET_VALUE (symbol, (valueT) frag_now_fix ());
       }
-#endif /* !NO_LISTING */
 
-#ifdef SEPARATE_STAB_SECTIONS
-  subseg_set (saved_seg, saved_subseg);
-#endif
+    S_SET_TYPE (symbol, type);
+    S_SET_OTHER (symbol, other);
+    S_SET_DESC (symbol, desc);
+  }
+#endif /* ! OBJ_PROCESS_STAB */
+#endif /* ! SEPARATE_STAB_SECTIONS */
+
+#ifndef NO_LISTING
+  if (listing)
+    {
+      switch (type)
+       {
+       case N_SLINE:
+         listing_source_line ((unsigned int) desc);
+         break;
+       case N_SO:
+       case N_SOL:
+         listing_source_file (string);
+         break;
+       }
+    }
+#endif /* ! NO_LISTING */
 
   demand_empty_rest_of_line ();
 }
index 913146e798f4e64475479a4eb8eb991e27adb0af..ea0349cb31ad8019e7982c3f5659e0f55c631730 100644 (file)
@@ -47,9 +47,12 @@ struct frag *data_last_frag; /* Last frag in segment. */
 static struct frag *bss_last_frag;     /* Last frag in segment. */
 #endif
 
+#if ! defined (BFD_ASSEMBLER) && ! defined (BFD)
 static object_headers headers;
-long string_byte_count;
 static char *the_object_file;
+#endif
+
+long string_byte_count;
 char *next_object_file_charP;  /* Tracks object file bytes. */
 
 #ifndef OBJ_VMS
@@ -69,9 +72,10 @@ static fixS *fix_new_internal PARAMS ((fragS *, int where, int size,
                                       offsetT offset, int pcrel,
                                       int r_type));
 #endif
+#if defined (BFD_ASSEMBLER) || !defined (BFD)
 static long fixup_segment PARAMS ((fixS * fixP, segT this_segment_type));
+#endif
 static relax_addressT relax_align PARAMS ((relax_addressT addr, int align));
-void relax_segment PARAMS ((struct frag * seg_frag_root, segT seg_type));
 
 /*
  *                     fix_new()
@@ -234,7 +238,7 @@ append (charPP, fromP, length)
   if (length == 0)
     return;
 
-  memcpy (*charPP, fromP, (int) length);
+  memcpy (*charPP, fromP, length);
   *charPP += length;
 }
 
@@ -318,6 +322,8 @@ remove_subsegs (head, seg, root, last)
 
 #endif /* BFD */
 
+#if defined (BFD_ASSEMBLER) || !defined (BFD)
+
 #ifdef BFD_ASSEMBLER
 static void
 cvt_frag_to_fill (sec, fragP)
@@ -391,6 +397,8 @@ cvt_frag_to_fill (headers, fragP)
     }
 }
 
+#endif /* defined (BFD_ASSEMBLER) || !defined (BFD) */
+
 #ifdef BFD_ASSEMBLER
 static void
 relax_and_size_seg (abfd, sec, xxx)
@@ -514,18 +522,27 @@ adjust_reloc_syms (abfd, sec, xxx)
        if (symsec == &bfd_und_section
            || symsec == &bfd_abs_section
            || bfd_is_com_section (symsec))
-         continue;
+         {
+           fixp->fx_addsy->sy_used_in_reloc = 1;
+           continue;
+         }
 
        /* Since we're reducing to section symbols, don't attempt to reduce
           anything that's already using one.  */
        if (sym->bsym == symsec->symbol)
-         continue;
+         {
+           fixp->fx_addsy->sy_used_in_reloc = 1;
+           continue;
+         }
 
        /* Is there some other reason we can't adjust this one?  (E.g.,
           call/bal links in i960-bout symbols.)  */
 #ifdef obj_fix_adjustable
        if (! obj_fix_adjustable (fixp))
-         continue;
+         {
+           fixp->fx_addsy->sy_used_in_reloc = 1;
+           continue;
+         }
 #endif
        /* If the section symbol isn't going to be output, the relocs
           at least should still work.  If not, figure out what to do
@@ -545,6 +562,7 @@ adjust_reloc_syms (abfd, sec, xxx)
              }
            symseginfo->sym = fixp->fx_addsy;
          }
+       fixp->fx_addsy->sy_used_in_reloc = 1;
       }
 
   dump_section_relocs (abfd, sec, stderr);
@@ -557,7 +575,8 @@ write_relocs (abfd, sec, xxx)
      char *xxx;
 {
   segment_info_type *seginfo = seg_info (sec);
-  int i, n;
+  int i;
+  unsigned int n;
   arelent **relocs;
   fixS *fixp;
 
@@ -582,7 +601,6 @@ write_relocs (abfd, sec, xxx)
   for (fixp = seginfo->fix_root; fixp != (fixS *) NULL; fixp = fixp->fx_next)
     {
       arelent *reloc;
-      extern arelent *tc_gen_reloc ();
       char *data;
       bfd_reloc_status_type s;
 
@@ -628,7 +646,6 @@ write_relocs (abfd, sec, xxx)
   for (fixp = seginfo->fix_root; fixp != (fixS *) NULL; fixp = fixp->fx_next)
     {
       arelent **reloc;
-      extern arelent **tc_gen_reloc ();
       char *data;
       bfd_reloc_status_type s;
       int j;
@@ -671,7 +688,8 @@ write_relocs (abfd, sec, xxx)
     bfd_set_reloc (stdoutput, sec, relocs, n);
   else
     bfd_set_section_flags (abfd, sec,
-                          bfd_get_section_flags (abfd, sec) & ~SEC_RELOC);
+                          (bfd_get_section_flags (abfd, sec)
+                           & (flagword) ~SEC_RELOC));
 #ifdef DEBUG2
   {
     int i;
@@ -697,39 +715,39 @@ write_contents (abfd, sec, xxx)
 {
   segment_info_type *seginfo = seg_info (sec);
   unsigned long offset = 0;
-  fragS *frags;
+  fragS *f;
 
   /* Write out the frags.  */
   if (! (bfd_get_section_flags (abfd, sec) & SEC_HAS_CONTENTS))
     return;
 
-  for (frags = seginfo->frchainP->frch_root;
-       frags;
-       frags = frags->fr_next)
+  for (f = seginfo->frchainP->frch_root;
+       f;
+       f = f->fr_next)
     {
       int x;
       unsigned long fill_size;
       char *fill_literal;
       long count;
 
-      assert (frags->fr_type == rs_fill);
-      if (frags->fr_fix)
+      assert (f->fr_type == rs_fill);
+      if (f->fr_fix)
        {
          x = bfd_set_section_contents (stdoutput, sec,
-                                       frags->fr_literal, offset,
-                                       frags->fr_fix);
+                                       f->fr_literal, (file_ptr) offset,
+                                       (bfd_size_type) f->fr_fix);
          assert (x == true);
-         offset += frags->fr_fix;
+         offset += f->fr_fix;
        }
-      fill_literal = frags->fr_literal + frags->fr_fix;
-      fill_size = frags->fr_var;
-      count = frags->fr_offset;
+      fill_literal = f->fr_literal + f->fr_fix;
+      fill_size = f->fr_var;
+      count = f->fr_offset;
       assert (count >= 0);
       if (fill_size && count)
        while (count--)
          {
            x = bfd_set_section_contents (stdoutput, sec,
-                                         fill_literal, offset,
+                                         fill_literal, (file_ptr) offset,
                                          (bfd_size_type) fill_size);
            assert (x == true);
            offset += fill_size;
@@ -738,7 +756,7 @@ write_contents (abfd, sec, xxx)
 }
 #endif
 
-#if defined(BFD_ASSEMBLER) || !defined (BFD)
+#if defined(BFD_ASSEMBLER) || (!defined (BFD) && !defined(OBJ_AOUT))
 static void
 merge_data_into_text ()
 {
@@ -766,7 +784,7 @@ merge_data_into_text ()
   data_fix_root = NULL;
 #endif
 }
-#endif /* BFD_ASSEMBLER || ! BFD */
+#endif /* BFD_ASSEMBLER || (! BFD && ! OBJ_AOUT) */
 
 #if !defined (BFD_ASSEMBLER) && !defined (BFD)
 static void
@@ -923,11 +941,7 @@ write_object_file ()
 #endif
   for (frchainP = frchain_root; frchainP; frchainP = frchainP->frch_next)
     {
-#ifdef BFD_ASSEMBLER
       subseg_set (frchainP->frch_seg, frchainP->frch_subseg);
-#else
-      subseg_new (frchainP->frch_seg, frchainP->frch_subseg);
-#endif
       frag_align (SUB_SEGMENT_ALIGN (now_seg), NOP_OPCODE);
       /* frag_align will have left a new frag.
         Use this last frag for an empty ".fill".
@@ -1259,7 +1273,8 @@ write_object_file ()
   /* Set up symbol table, and write it out.  */
   if (symbol_rootP)
     {
-      int i = 0, n;
+      unsigned int i = 0;
+      unsigned int n;
       symbolS *symp;
 
       for (symp = symbol_rootP; symp; symp = symbol_next (symp))
@@ -1290,27 +1305,30 @@ write_object_file ()
                  symp->bsym->flags,
                  segment_name (symp->bsym->section));
 #endif
-         {
-#ifdef obj_frob_symbol
+         if (! symp->sy_used_in_reloc)
            {
-             int punt = 0;
-             obj_frob_symbol (symp, punt);
-             if (punt)
-               goto punt_it;
-           }
+#ifdef obj_frob_symbol
+             {
+               int punt = 0;
+               obj_frob_symbol (symp, punt);
+               if (punt)
+                 goto punt_it;
+             }
 #endif
 #ifdef tc_frob_symbol
-           {
-             int punt = 0;
-             tc_frob_symbol (symp, punt);
-             if (punt)
-               goto punt_it;
-           }
+             {
+               int punt = 0;
+               tc_frob_symbol (symp, punt);
+               if (punt)
+                 goto punt_it;
+             }
 #endif
-         }
+           }
+
          /* If we don't want to keep this symbol, splice it out of the
             chain now.  */
-         if (S_IS_LOCAL (symp))
+         if (! symp->sy_used_in_reloc
+             && S_IS_LOCAL (symp))
            {
              symbolS *prev, *next;
 #if defined (obj_frob_symbol) || defined (tc_frob_symbol)
@@ -1343,6 +1361,14 @@ write_object_file ()
              continue;
            }
 
+         /* Make sure we really got a value for the symbol.  */
+         if (! symp->sy_resolved)
+           {
+             as_bad ("can't resolve value for symbol \"%s\"",
+                     S_GET_NAME (symp));
+             symp->sy_resolved = 1;
+           }
+
          /* Set the value into the BFD symbol.  Up til now the value
             has only been kept in the gas symbolS struct.  */
          symp->bsym->value = S_GET_VALUE (symp);
@@ -1506,7 +1532,6 @@ relax_segment (segment_frag_root, segment)
            symbolS *symbolP;
            long target;
            long after;
-           long aim;
 
            was_address = fragP->fr_address;
            address = fragP->fr_address += stretch;
@@ -1552,7 +1577,7 @@ relax_segment (segment_frag_root, segment)
                          if (flagseen['K'])
                            {
                              char buf[50];
-                             sprint_value (buf, lie->addnum);
+                             sprint_value (buf, (addressT) lie->addnum);
                              as_warn (".word %s-%s+%s didn't fit",
                                       S_GET_NAME (lie->add),
                                       S_GET_NAME (lie->sub),
@@ -1623,6 +1648,7 @@ relax_segment (segment_frag_root, segment)
                  const relax_typeS *start_type;
                  relax_substateT next_state;
                  relax_substateT this_state;
+                 long aim;
 
                  this_state = fragP->fr_subtype;
                  start_type = this_type = md_relax_table + this_state;
@@ -1630,6 +1656,7 @@ relax_segment (segment_frag_root, segment)
 
                  if (symbolP)
                    {
+#ifndef DIFF_EXPR_OK
 #if !defined (MANY_SEGMENTS) && !defined (BFD_ASSEMBLER)
                      know ((S_GET_SEGMENT (symbolP) == SEG_ABSOLUTE)
                            || (S_GET_SEGMENT (symbolP) == SEG_DATA)
@@ -1637,6 +1664,7 @@ relax_segment (segment_frag_root, segment)
                            || (S_GET_SEGMENT (symbolP) == SEG_TEXT));
 #endif
                      know (symbolP->sy_frag);
+#endif
                      know (!(S_GET_SEGMENT (symbolP) == absolute_section)
                            || symbolP->sy_frag == &zero_address_frag);
                      target +=
@@ -1733,6 +1761,8 @@ relax_segment (segment_frag_root, segment)
    */
 }                              /* relax_segment() */
 
+#if defined (BFD_ASSEMBLER) || !defined (BFD)
+
 /* fixup_segment()
 
    Go through all the fixS's in a segment and see which ones can be
@@ -1806,6 +1836,7 @@ fixup_segment (fixP, this_segment_type)
            if (!add_symbolP)
              {
                /* Its just -sym */
+               /* @@ Should try converting to pcrel ref to fixed addr.  */
                if (S_GET_SEGMENT (sub_symbolP) != absolute_section)
                  as_bad ("Negative of non-absolute symbol %s",
                          S_GET_NAME (sub_symbolP));
@@ -1843,6 +1874,19 @@ fixup_segment (fixP, this_segment_type)
                  {
                    add_number -= S_GET_VALUE (sub_symbolP);
                  }
+#ifdef DIFF_EXPR_OK
+               else if (!pcrel
+                        && S_GET_SEGMENT (sub_symbolP) == this_segment_type)
+                 {
+                   /* Make it pc-relative.  */
+                   add_number += (md_pcrel_from (fixP)
+                                  - S_GET_VALUE (sub_symbolP));
+                   pcrel = 1;
+                   fixP->fx_pcrel = 1;
+                   sub_symbolP = 0;
+                   fixP->fx_subsy = 0;
+                 }
+#endif
                else
                  {
                    char buf[50];
@@ -1961,8 +2005,9 @@ fixup_segment (fixP, this_segment_type)
            if (!flagseen['J']
                && size == 2
                && add_number > 0x7fff)
-             as_bad ("Signed .word overflow; switch may be too large; %d at 0x%x",
-                     add_number, fragP->fr_address + where);
+             as_bad ("Signed .word overflow; switch may be too large; %ld at 0x%lx",
+                     (long) add_number,
+                     (unsigned long) (fragP->fr_address + where));
 #endif
          }                     /* not a bit fix */
 
@@ -1987,4 +2032,6 @@ fixup_segment (fixP, this_segment_type)
   return (seg_reloc_count);
 }
 
+#endif /* defined (BFD_ASSEMBLER) || !defined (BFD) */
+
 /* end of write.c */