* read.c (abs_section_offset): New global variable.
authorIan Lance Taylor <ian@airs.com>
Wed, 9 Aug 1995 19:36:25 +0000 (19:36 +0000)
committerIan Lance Taylor <ian@airs.com>
Wed, 9 Aug 1995 19:36:25 +0000 (19:36 +0000)
(potable): Add offset, struct.
(do_org): New static function; handle changing the origin in the
absolute section.
(s_org): Use do_org.
(s_set): Likewise.
(equals): Likewise.
(s_space): In absolute_section, just increase abs_section_offset.
(s_struct): New function.
(emit_expr): Handle absolute_section specially.
* read.h (abs_section_offset): Declare.
(s_struct): Declare.

* read.c (potable): Add ifeq, ifge, ifgt, ifle, iflt, ifne.
Change if to pass O_ne to s_if.
(read_a_source_file): Don't define an label without a colon if
ignore_input returns true.

* read.c (potable): Add dcb, dcb.b, dcb.d, dcb.l, dcb.s, dcb.w,
dcb.x, ds.d, ds.p, ds.s, ds.x, elsec, endc, fail, format, llen,
noformat.
(read_a_source_file): If pseudo-op handler is s_end, quit
immediately.
(s_end): New function.
(s_fail): New function.
(s_float_space): New function.
(hex_float): New static function.
(float_cons): Use hex_float.
* read.h (s_fail): Declare.
(s_float_space): Declare.

gas/ChangeLog
gas/read.c
gas/read.h

index 4955aaa7bb239b5272835b57779dd3515b443c68..09e0b74284a81d674decc293b81da6a017a6e601 100644 (file)
@@ -1,5 +1,63 @@
 Wed Aug  9 10:51:48 1995  Ian Lance Taylor  <ian@cygnus.com>
 
+       * write.c (adjust_reloc_syms): Check that symbol is not NULL
+       before checking sy_mri_common.
+       (fixup_segment): Likewise.
+       * config/obj-coff.c (fixup_segment): Likewise.
+
+       * read.c (abs_section_offset): New global variable.
+       (potable): Add offset, struct.
+       (do_org): New static function; handle changing the origin in the
+       absolute section.
+       (s_org): Use do_org.
+       (s_set): Likewise.
+       (equals): Likewise.
+       (s_space): In absolute_section, just increase abs_section_offset.
+       (s_struct): New function.
+       (emit_expr): Handle absolute_section specially.
+       * read.h (abs_section_offset): Declare.
+       (s_struct): Declare.
+       * frags.c (frag_more): Warn if in absolute_section.
+       (frag_now_fix): In absolute_section, return abs_section_offset.
+       * subsegs.c (subseg_change): If switching to absolute_section,
+       just set now_seg and now_subseg.
+       (subseg_set_rest): Special handling when switching to or from
+       absolute_section.
+
+       * config/tc-m68k.c (m68k_float_copnum): New static variable.
+       (md_pseudo_table): Add fopt and mask2.
+       (m68k_ip): Use m68k_float_copnum, not COPNUM, when setting
+       coprocessor register to use.  In case 'I' when checking operands,
+       correct coprocessor register numbers.  In case 'I' when setting
+       operands, don't add 1.
+       (s_fopt): New static function.
+       * config/m68k-parse.h (COPNUM): Don't define.
+
+       * read.c (potable): Add ifeq, ifge, ifgt, ifle, iflt, ifne.
+       Change if to pass O_ne to s_if.
+       (read_a_source_file): Don't define an label without a colon if
+       ignore_input returns true.
+       * cond.c (s_if): Treat argument as an operatorT describing how to
+       compare the argument against zero.
+       (ignore_input): Don't require an initial dot in MRI mode, or if
+       NO_PSEUDO_DOT is defined.
+
+       * read.c (potable): Add dcb, dcb.b, dcb.d, dcb.l, dcb.s, dcb.w,
+       dcb.x, ds.d, ds.p, ds.s, ds.x, elsec, endc, fail, format, llen,
+       noformat.
+       (read_a_source_file): If pseudo-op handler is s_end, quit
+       immediately.
+       (s_end): New function.
+       (s_fail): New function.
+       (s_float_space): New function.
+       (hex_float): New static function.
+       (float_cons): Use hex_float.
+       * read.h (s_fail): Declare.
+       (s_float_space): Declare.
+       * cond.c (s_end): Remove.
+       * listing.c (listing_psize): Treat argument as indicating whether
+       a height is expected.
+
        * read.c (mri_pending_align): New static variable.
        (read_a_source_file): Handle mri_pending_align.
        (cons): Set mri_pending_align if appropriate.
index c77f5887405578120804efbd94825dd13c5da464..af8c775cba4e5ebea152da2958779bcc44fb92b0 100644 (file)
@@ -169,6 +169,11 @@ struct broken_word *broken_words;
 int new_broken_words;
 #endif
 
+/* The current offset into the absolute section.  We don't try to
+   build frags in the absolute section, since no data can be stored
+   there.  We just keep track of the current offset.  */
+addressT abs_section_offset;
+
 /* If this line had an MRI style label, it is stored in this variable.
    This is used by some of the MRI pseudo-ops.  */
 static symbolS *mri_line_label;
@@ -185,6 +190,8 @@ symbolS *mri_common_symbol;
 static int mri_pending_align;
 
 static void do_align PARAMS ((int, char *));
+static int hex_float PARAMS ((int, char *));
+static void do_org PARAMS ((segT, expressionS *, int));
 char *demand_copy_string PARAMS ((int *lenP));
 int is_it_end_of_statement PARAMS ((void));
 static segT get_segmented_expression PARAMS ((expressionS *expP));
@@ -238,10 +245,21 @@ static const pseudo_typeS potable[] =
   {"dc.s", float_cons, 'f'},
   {"dc.w", cons, 2},
   {"dc.x", float_cons, 'x'},
+  {"dcb", s_space, 2},
+  {"dcb.b", s_space, 1},
+  {"dcb.d", s_float_space, 'd'},
+  {"dcb.l", s_space, 4},
+  {"dcb.s", s_float_space, 'f'},
+  {"dcb.w", s_space, 2},
+  {"dcb.x", s_float_space, 'x'},
   {"ds", s_space, 2},
   {"ds.b", s_space, 1},
+  {"ds.d", s_space, 8},
   {"ds.l", s_space, 4},
+  {"ds.p", s_space, 12},
+  {"ds.s", s_space, 4},
   {"ds.w", s_space, 2},
+  {"ds.x", s_space, 12},
 #ifdef S_SET_DESC
   {"desc", s_desc, 0},
 #endif
@@ -250,7 +268,9 @@ static const pseudo_typeS potable[] =
 /* dsect */
   {"eject", listing_eject, 0}, /* Formfeed listing */
   {"else", s_else, 0},
+  {"elsec", s_else, 0},
   {"end", s_end, 0},
+  {"endc", s_endif, 0},
   {"endif", s_endif, 0},
 /* endef */
   {"equ", s_set, 0},
@@ -259,16 +279,24 @@ static const pseudo_typeS potable[] =
   {"extern", s_ignore, 0},     /* We treat all undef as ext */
   {"appfile", s_app_file, 1},
   {"appline", s_app_line, 0},
+  {"fail", s_fail, 0},
   {"file", s_app_file, 0},
   {"fill", s_fill, 0},
   {"float", float_cons, 'f'},
+  {"format", s_ignore, 0},
   {"global", s_globl, 0},
   {"globl", s_globl, 0},
   {"hword", cons, 2},
-  {"if", s_if, 0},
+  {"if", s_if, (int) O_ne},
   {"ifdef", s_ifdef, 0},
+  {"ifeq", s_if, (int) O_eq},
   {"ifeqs", s_ifeqs, 0},
+  {"ifge", s_if, (int) O_ge},
+  {"ifgt", s_if, (int) O_gt},
+  {"ifle", s_if, (int) O_le},
+  {"iflt", s_if, (int) O_lt},
   {"ifndef", s_ifdef, 1},
+  {"ifne", s_if, (int) O_ne},
   {"ifnes", s_ifeqs, 1},
   {"ifnotdef", s_ifdef, 1},
   {"include", s_include, 0},
@@ -276,10 +304,13 @@ static const pseudo_typeS potable[] =
   {"lcomm", s_lcomm, 0},
   {"lflags", listing_flags, 0},        /* Listing flags */
   {"list", listing_list, 1},   /* Turn listing on */
+  {"llen", listing_psize, 1},
   {"long", cons, 4},
   {"lsym", s_lsym, 0},
+  {"noformat", s_ignore, 0},
   {"nolist", listing_list, 0}, /* Turn listing off */
   {"octa", cons, 16},
+  {"offset", s_struct, 0},
   {"org", s_org, 0},
   {"p2align", s_align_ptwo, 0},
   {"psize", listing_psize, 0}, /* set paper size */
@@ -297,6 +328,7 @@ static const pseudo_typeS potable[] =
   {"stabn", s_stab, 'n'},
   {"stabs", s_stab, 's'},
   {"string", stringer, 1},
+  {"struct", s_struct, 0},
 /* tag */
   {"text", s_text, 0},
 
@@ -433,22 +465,28 @@ read_a_source_file (name)
                      char *line_start = input_line_pointer;
                      char c = get_symbol_end ();
 
-                     /* In MRI mode, the EQU pseudoop must be handled
-                         specially.  */
-                     if (flag_mri)
+                     if (! ignore_input ())
                        {
-                         if ((strncasecmp (input_line_pointer + 1, "EQU", 3)
-                              == 0)
-                             && (input_line_pointer[4] == ' '
-                                 || input_line_pointer[4] == '\t'))
+                         /* In MRI mode, the EQU pseudoop must be
+                            handled specially.  */
+                         if (flag_mri)
                            {
-                             input_line_pointer += 4;
-                             equals (line_start);
-                             continue;
+                             if (((strncasecmp (input_line_pointer + 1,
+                                                "EQU", 3) == 0)
+                                  || (strncasecmp (input_line_pointer + 1,
+                                                   "SET", 3) == 0))
+                                 && (input_line_pointer[4] == ' '
+                                     || input_line_pointer[4] == '\t'))
+                               {
+                                 input_line_pointer += 4;
+                                 equals (line_start);
+                                 continue;
+                               }
                            }
+
+                         mri_line_label = colon (line_start);
                        }
 
-                     mri_line_label = colon (line_start);
                      *input_line_pointer = c;
                      if (c == ':')
                        input_line_pointer++;
@@ -595,6 +633,10 @@ read_a_source_file (name)
                       * after pseudo-operation.
                       */
                      (*pop->poc_handler) (pop->poc_val);
+
+                     /* If that was .end, just get out now.  */
+                     if (pop->poc_handler == s_end)
+                       goto quit;
                    }
                  else
                    {           /* machine instruction */
@@ -810,8 +852,9 @@ read_a_source_file (name)
            }
        }
     }                          /* while (more buffers to scan) */
-  input_scrub_close ();                /* Close the input file */
 
+ quit:
+  input_scrub_close ();                /* Close the input file */
 }
 
 void 
@@ -1173,6 +1216,39 @@ s_app_line (ignore)
   demand_empty_rest_of_line ();
 }
 
+/* Handle the .end pseudo-op.  Actually, the real work is done in
+   read_a_source_file.  */
+
+void
+s_end (ignore)
+     int ignore;
+{
+  if (flag_mri)
+    {
+      /* The MRI assembler permits the start symbol to follow .end,
+         but we don't support that.  */
+      SKIP_WHITESPACE ();
+      if (! is_end_of_line[(unsigned char) *input_line_pointer])
+       as_warn ("start address not supported");
+    }
+}
+
+/* Handle the MRI fail pseudo-op.  */
+
+void
+s_fail (ignore)
+     int ignore;
+{
+  offsetT temp;
+
+  temp = get_absolute_expression ();
+  if (temp >= 500)
+    as_warn (".fail %ld encountered", (long) temp);
+  else
+    as_bad (".fail %ld encountered", (long) temp);
+  demand_empty_rest_of_line ();
+}
+
 void 
 s_fill (ignore)
      int ignore;
@@ -1486,6 +1562,39 @@ s_lsym (ignore)
   demand_empty_rest_of_line ();
 }                              /* s_lsym() */
 
+/* Handle changing the location counter.  */
+
+static void
+do_org (segment, exp, fill)
+     segT segment;
+     expressionS *exp;
+     int fill;
+{
+  if (segment != now_seg && segment != absolute_section)
+    as_bad ("invalid segment \"%s\"; segment \"%s\" assumed",
+           segment_name (segment), segment_name (now_seg));
+
+  if (now_seg == absolute_section)
+    {
+      if (fill != 0)
+       as_warn ("ignoring fill value in absolute section");
+      if (exp->X_op != O_constant)
+       {
+         as_bad ("only constant offsets supported in absolute section");
+         exp->X_add_number = 0;
+       }
+      abs_section_offset = exp->X_add_number;
+    }
+  else
+    {
+      char *p;
+
+      p = frag_var (rs_org, 1, 1, (relax_substateT) 0, exp->X_add_symbol,
+                   exp->X_add_number, (char *) NULL);
+      *p = fill;
+    }
+}
+
 void 
 s_org (ignore)
      int ignore;
@@ -1493,7 +1602,7 @@ s_org (ignore)
   register segT segment;
   expressionS exp;
   register long temp_fill;
-  register char *p;
+
   /* Don't believe the documentation of BSD 4.2 AS.  There is no such
      thing as a sub-segment-relative origin.  Any absolute origin is
      given a warning, then assumed to be segment-relative.  Any
@@ -1514,15 +1623,10 @@ s_org (ignore)
     }
   else
     temp_fill = 0;
+
   if (!need_pass_2)
-    {
-      if (segment != now_seg && segment != absolute_section)
-       as_bad ("Invalid segment \"%s\". Segment \"%s\" assumed.",
-               segment_name (segment), segment_name (now_seg));
-      p = frag_var (rs_org, 1, 1, (relax_substateT) 0, exp.X_add_symbol,
-                   exp.X_add_number, (char *) 0);
-      *p = temp_fill;
-    }                          /* if (ok to make frag) */
+    do_org (segment, &exp, temp_fill);
+
   demand_empty_rest_of_line ();
 }                              /* s_org() */
 
@@ -1568,15 +1672,7 @@ s_set (ignore)
       segment = get_known_segmented_expression (&exp);
 
       if (!need_pass_2)
-       {
-         if (segment != now_seg && segment != absolute_section)
-           as_bad ("Invalid segment \"%s\". Segment \"%s\" assumed.",
-                   segment_name (segment),
-                   segment_name (now_seg));
-         ptr = frag_var (rs_org, 1, 1, (relax_substateT) 0, exp.X_add_symbol,
-                         exp.X_add_number, (char *) 0);
-         *ptr = 0;
-       }                       /* if (ok to make frag) */
+       do_org (segment, &exp, 0);
 
       *end_name = delim;
       return;
@@ -1629,6 +1725,14 @@ s_space (mult)
          return;
        }
 
+      /* If we are in the absolute section, just bump the offset.  */
+      if (now_seg == absolute_section)
+       {
+         abs_section_offset += repeat;
+         demand_empty_rest_of_line ();
+         return;
+       }
+
       /* If we are secretly in an MRI common section, then creating
          space just increases the size of the common symbol.  */
       if (mri_common_symbol != NULL)
@@ -1645,6 +1749,11 @@ s_space (mult)
     }
   else
     {
+      if (now_seg == absolute_section)
+       {
+         as_bad ("space allocation too complex in absolute section");
+         subseg_set (text_section, 0);
+       }
       if (mri_common_symbol != NULL)
        {
          as_bad ("space allocation too complex in common section");
@@ -1671,6 +1780,85 @@ s_space (mult)
   demand_empty_rest_of_line ();
 }
 
+/* This is like s_space, but the value is a floating point number with
+   the given precision.  This is for the MRI dcb.s pseudo-op and
+   friends.  */
+
+void
+s_float_space (float_type)
+     int float_type;
+{
+  offsetT count;
+  int flen;
+  char temp[MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT];
+
+  count = get_absolute_expression ();
+
+  SKIP_WHITESPACE ();
+  if (*input_line_pointer != ',')
+    {
+      as_bad ("missing value");
+      ignore_rest_of_line ();
+      return;
+    }
+
+  ++input_line_pointer;
+
+  SKIP_WHITESPACE ();
+
+  /* Skip any 0{letter} that may be present.  Don't even check if the
+   * letter is legal.  */
+  if (input_line_pointer[0] == '0' && isalpha (input_line_pointer[1]))
+    input_line_pointer += 2;
+
+  /* Accept :xxxx, where the x's are hex digits, for a floating point
+     with the exact digits specified.  */
+  if (input_line_pointer[0] == ':')
+    {
+      flen = hex_float (float_type, temp);
+      if (flen < 0)
+       {
+         ignore_rest_of_line ();
+         return;
+       }
+    }
+  else
+    {
+      char *err;
+
+      err = md_atof (float_type, temp, &flen);
+      know (flen <= MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT);
+      know (flen > 0);
+      if (err)
+       {
+         as_bad ("Bad floating literal: %s", err);
+         ignore_rest_of_line ();
+         return;
+       }
+    }
+
+  while (--count >= 0)
+    {
+      char *p;
+
+      p = frag_more (flen);
+      memcpy (p, temp, (unsigned int) flen);
+    }
+
+  demand_empty_rest_of_line ();
+}
+
+/* Handle the .struct pseudo-op, as found in MIPS assemblers.  */
+
+void
+s_struct (ignore)
+     int ignore;
+{
+  abs_section_offset = get_absolute_expression ();
+  subseg_set (absolute_section, 0);
+  demand_empty_rest_of_line ();
+}
+
 void
 s_text (ignore)
      int ignore;
@@ -1927,6 +2115,15 @@ emit_expr (exp, nbytes)
 
   op = exp->X_op;
 
+  /* Allow `.word 0' in the absolute section.  */
+  if (now_seg == absolute_section)
+    {
+      if (op != O_constant || exp->X_add_number != 0)
+       as_bad ("attempt to store value in absolute section");
+      abs_section_offset += nbytes;
+      return;
+    }
+
   /* Handle a negative bignum.  */
   if (op == O_uminus
       && exp->X_add_number == 0
@@ -2379,6 +2576,88 @@ parse_repeat_cons (exp, nbytes)
 
 #endif /* REPEAT_CONS_EXPRESSIONS */
 \f
+/* Parse a floating point number represented as a hex constant.  This
+   permits users to specify the exact bits they want in the floating
+   point number.  */
+
+static int
+hex_float (float_type, bytes)
+     int float_type;
+     char *bytes;
+{
+  int length;
+  int i;
+
+  switch (float_type)
+    {
+    case 'f':
+    case 'F':
+    case 's':
+    case 'S':
+      length = 4;
+      break;
+
+    case 'd':
+    case 'D':
+    case 'r':
+    case 'R':
+      length = 8;
+      break;
+
+    case 'x':
+    case 'X':
+      length = 12;
+      break;
+
+    case 'p':
+    case 'P':
+      length = 12;
+      break;
+
+    default:
+      as_bad ("Unknown floating type type '%c'", float_type);
+      return -1;
+    }
+
+  /* It would be nice if we could go through expression to parse the
+     hex constant, but if we get a bignum it's a pain to sort it into
+     the buffer correctly.  */
+  i = 0;
+  while (hex_p (*input_line_pointer) || *input_line_pointer == '_')
+    {
+      int d;
+
+      /* The MRI assembler accepts arbitrary underscores strewn about
+        through the hex constant, so we ignore them as well. */
+      if (*input_line_pointer == '_')
+       {
+         ++input_line_pointer;
+         continue;
+       }
+
+      if (i >= length)
+       {
+         as_warn ("Floating point constant too large");
+         return -1;
+       }
+      d = hex_value (*input_line_pointer) << 4;
+      ++input_line_pointer;
+      while (*input_line_pointer == '_')
+       ++input_line_pointer;
+      if (hex_p (*input_line_pointer))
+       {
+         d += hex_value (*input_line_pointer);
+         ++input_line_pointer;
+       }
+      bytes[i++] = d;
+    }
+
+  if (i < length)
+    memset (bytes + i, 0, length - i);
+
+  return length;
+}
+
 /*
  *                     float_cons()
  *
@@ -2432,77 +2711,13 @@ float_cons (float_type)
          point with the exact digits specified.  */
       if (input_line_pointer[0] == ':')
        {
-         int i;
-
-         switch (float_type)
+         ++input_line_pointer;
+         length = hex_float (float_type, temp);
+         if (length < 0)
            {
-           case 'f':
-           case 'F':
-           case 's':
-           case 'S':
-             length = 4;
-             break;
-
-           case 'd':
-           case 'D':
-           case 'r':
-           case 'R':
-             length = 8;
-             break;
-
-           case 'x':
-           case 'X':
-             length = 12;
-             break;
-
-           case 'p':
-           case 'P':
-             length = 12;
-             break;
-
-           default:
-             as_bad ("Unknown floating type type '%c'", float_type);
              ignore_rest_of_line ();
              return;
            }
-
-         /* It would be nice if we could go through expression to
-             parse the hex constant, but if we get a bignum it's a
-             pain to sort it into the buffer correctly.  */
-         i = 0;
-         ++input_line_pointer;
-         while (hex_p (*input_line_pointer) || *input_line_pointer == '_')
-           {
-             int d;
-
-             /* The MRI assembler accepts arbitrary underscores
-                 strewn about through the hex constant, so we ignore
-                 them as well. */
-             if (*input_line_pointer == '_')
-               {
-                 ++input_line_pointer;
-                 continue;
-               }
-
-             if (i >= length)
-               {
-                 as_warn ("Floating point constant too large");
-                 ignore_rest_of_line ();
-                 return;
-               }
-             d = hex_value (*input_line_pointer) << 4;
-             ++input_line_pointer;
-             while (*input_line_pointer == '_')
-               ++input_line_pointer;
-             if (hex_p (*input_line_pointer))
-               {
-                 d += hex_value (*input_line_pointer);
-                 ++input_line_pointer;
-               }
-             temp[i++] = d;
-           }
-         if (i < length)
-           memset (temp + i, 0, length - i);
        }
       else
        {
@@ -2924,15 +3139,7 @@ equals (sym_name)
 
       segment = get_known_segmented_expression (&exp);
       if (!need_pass_2)
-       {
-         if (segment != now_seg && segment != absolute_section)
-           as_warn ("Illegal segment \"%s\". Segment \"%s\" assumed.",
-                    segment_name (segment),
-                    segment_name (now_seg));
-         p = frag_var (rs_org, 1, 1, (relax_substateT) 0, exp.X_add_symbol,
-                       exp.X_add_number, (char *) 0);
-         *p = 0;
-       }                       /* if (ok to make frag) */
+       do_org (segment, &exp, 0);
     }
   else
     {
index 3a3d82dfe20fed81ef3e8a98b29f4c093f83d9df..4a00b327cc8590c3d9d73b4a0c41ed940bed5b35 100644 (file)
@@ -60,6 +60,9 @@ extern const char line_separator_chars[];
 /* This flag whether to generate line info for asm file */
 extern int generate_asm_lineno;
 
+/* The offset in the absolute section.  */
+extern addressT abs_section_offset;
+
 /* This is used to support MRI common sections.  */
 extern symbolS *mri_common_symbol;
 
@@ -86,13 +89,14 @@ void s_align_ptwo PARAMS ((int));
 void s_app_file PARAMS ((int));
 void s_app_line PARAMS ((int));
 void s_comm PARAMS ((int));
-void s_mri_common PARAMS ((int));
 void s_data PARAMS ((int));
 void s_desc PARAMS ((int));
 void s_else PARAMS ((int arg));
 void s_end PARAMS ((int arg));
 void s_endif PARAMS ((int arg));
+void s_fail PARAMS ((int));
 void s_fill PARAMS ((int));
+void s_float_space PARAMS ((int mult));
 void s_globl PARAMS ((int arg));
 void s_if PARAMS ((int arg));
 void s_ifdef PARAMS ((int arg));
@@ -101,10 +105,12 @@ void s_ignore PARAMS ((int arg));
 void s_include PARAMS ((int arg));
 void s_lcomm PARAMS ((int needs_align));
 void s_lsym PARAMS ((int));
+void s_mri_common PARAMS ((int));
 void s_org PARAMS ((int));
 void s_set PARAMS ((int));
 void s_space PARAMS ((int mult));
 void s_stab PARAMS ((int what));
+void s_struct PARAMS ((int));
 void s_text PARAMS ((int));
 void stringer PARAMS ((int append_zero));
 void s_xstab PARAMS ((int what));