* app.c (do_scrub_begin): Let line_comment_chars override
authorIan Lance Taylor <ian@airs.com>
Thu, 27 May 1993 19:29:38 +0000 (19:29 +0000)
committerIan Lance Taylor <ian@airs.com>
Thu, 27 May 1993 19:29:38 +0000 (19:29 +0000)
comment_chars.
(do_scrub_next_char): If a line comment character is not at the
start of a line, treat it as a comment character if it is one.
For a CPP line comment use pseudo-op .appline rather than .line.
* input-scrub.c (logical_input_line): Make int rather than
unsigned.
(input_scrub_push, input_scrub_begin): Initialize
logical_input_line to -1 rather than 0.
(bump_line_counters): Increment logical_input_line.
(new_logical_line): If line_number is -2, decrement
logical_input_line.
(as_where): Use logical_input_line even if it is 0.
* read.h (s_app_file prototype): Now takes an int argument.
* read.c (potable): Make .appfile call s_app_file with 1.  New
.appline pseudo-op calls s_app_line.
(s_app_file): If .appfile, call new_logical_line with -2 to
account for newline inserted by do_scrub_next_char.  If listing,
call listing_source_file.
(s_app_line): New function to handle fake pseudo-op .appline.
* config/obj-coff.c (obj_pseudo_table): Make .appline call
obj_coff_ln.
(obj_coff_ln): Added argument to indicate whether .appline.
* config/obj-coffbfd.c (obj_pseudo_table): Make .appline call
obj_coff_ln.
(obj_coff_ln): Added argument to indicate whether .appline.
* config/tc-mips.c (s_file): Pass argument to s_app_file.

gas/ChangeLog
gas/app.c
gas/config/obj-coffbfd.c
gas/config/tc-mips.c
gas/read.c

index ae17364..7c039b9 100644 (file)
@@ -1,3 +1,33 @@
+Thu May 27 11:07:50 1993  Ian Lance Taylor  (ian@cygnus.com)
+
+       * app.c (do_scrub_begin): Let line_comment_chars override
+       comment_chars.
+       (do_scrub_next_char): If a line comment character is not at the
+       start of a line, treat it as a comment character if it is one.
+       For a CPP line comment use pseudo-op .appline rather than .line.
+       * input-scrub.c (logical_input_line): Make int rather than
+       unsigned.
+       (input_scrub_push, input_scrub_begin): Initialize
+       logical_input_line to -1 rather than 0.
+       (bump_line_counters): Increment logical_input_line.
+       (new_logical_line): If line_number is -2, decrement
+       logical_input_line.
+       (as_where): Use logical_input_line even if it is 0.
+       * read.h (s_app_file prototype): Now takes an int argument.
+       * read.c (potable): Make .appfile call s_app_file with 1.  New
+       .appline pseudo-op calls s_app_line.
+       (s_app_file): If .appfile, call new_logical_line with -2 to
+       account for newline inserted by do_scrub_next_char.  If listing,
+       call listing_source_file.
+       (s_app_line): New function to handle fake pseudo-op .appline.
+       * config/obj-coff.c (obj_pseudo_table): Make .appline call
+       obj_coff_ln.
+       (obj_coff_ln): Added argument to indicate whether .appline.
+       * config/obj-coffbfd.c (obj_pseudo_table): Make .appline call
+       obj_coff_ln.
+       (obj_coff_ln): Added argument to indicate whether .appline.
+       * config/tc-mips.c (s_file): Pass argument to s_app_file.
+
 Tue May 25 11:59:07 1993  Ian Lance Taylor  (ian@cygnus.com)
 
        * config/obj-bout.h (S_GET_VALUE): Removed unnecessary cast.
index 1983c3c..01fea74 100644 (file)
--- a/gas/app.c
+++ b/gas/app.c
@@ -23,7 +23,7 @@
 
 /* App, the assembler pre-processor.  This pre-processor strips out excess
    spaces, turns single-quoted characters into a decimal constant, and turns
-   # <number> <filename> <garbage> into a .line <number>\n.app-file <filename>
+   # <number> <filename> <garbage> into a .line <number>\n.file <filename>
    pair.  This needs better error-handling.
    */
 
@@ -87,16 +87,16 @@ do_scrub_begin ()
       lex[*p] = LEX_IS_SYMBOL_COMPONENT;
     }                          /* declare symbol characters */
 
-  for (p = line_comment_chars; *p; p++)
-    {
-      lex[*p] = LEX_IS_LINE_COMMENT_START;
-    }                          /* declare line comment chars */
-
   for (p = comment_chars; *p; p++)
     {
       lex[*p] = LEX_IS_COMMENT_START;
     }                          /* declare comment chars */
 
+  for (p = line_comment_chars; *p; p++)
+    {
+      lex[*p] = LEX_IS_LINE_COMMENT_START;
+    }                          /* declare line comment chars */
+
   for (p = line_separator_chars; *p; p++)
     {
       lex[*p] = LEX_IS_LINE_SEPARATOR;
@@ -247,19 +247,19 @@ do_scrub_next_char (get, unget)
          4: after putting out a .line, put out digits
          5: parsing a string, then go to old-state
          6: putting out \ escape in a "d string.
-         7: After putting out a .app-file, put out string.
-         8: After putting out a .app-file string, flush until newline.
+         7: After putting out a .appfile, put out string.
+         8: After putting out a .appfile string, flush until newline.
          9: After seeing symbol char in state 3 (keep 1white after symchar)
+        10: After seeing whitespace in state 9 (keep white before symchar)
          -1: output string in out_string and go to the state in old_state
          -2: flush text until a '*' '/' is seen, then go to state old_state
          */
 
-  /* I added state 9 because the MIPS ECOFF assembler uses constructs
-     like ``.loc 1 20''.  This was turning into ``.loc 120''.  State 9
-     ensures that a space is never dropped immediately following a
-     character which could appear in a identifier.  It is still
-     dropped following a comma, so this has no effect for most
-     assemblers.  I hope.  Ian Taylor, ian@cygnus.com.  */
+  /* I added states 9 and 10 because the MIPS ECOFF assembler uses
+     constructs like ``.loc 1 20''.  This was turning into ``.loc
+     120''.  States 9 and 10 ensure that a space is never dropped in
+     between characters which could appear in a identifier.  Ian
+     Taylor, ian@cygnus.com.  */
 
   register int ch, ch2 = 0;
 
@@ -308,7 +308,7 @@ do_scrub_next_char (get, unget)
          if (ch == '"')
            {
              (*unget) (ch);
-             out_string = "\n.app-file ";
+             out_string = "\n.appfile ";
              old_state = 7;
              state = -1;
              return *out_string++;
@@ -406,7 +406,7 @@ do_scrub_next_char (get, unget)
       return ch;
     }
 
-  /* OK, we are somewhere in states 0 through 4 or 9 */
+  /* OK, we are somewhere in states 0 through 4 or 9 through 10 */
 
   /* flushchar: */
   ch = (*get) ();
@@ -454,12 +454,15 @@ recycle:
        case 1:
          BAD_CASE (state);     /* We can't get here */
        case 2:
-       case 9:
          state = 3;
          (*unget) (ch);
          return ' ';           /* Sp after opco */
        case 3:
          goto recycle;         /* Sp in operands */
+       case 9:
+       case 10:
+         state = 10;           /* Sp after symbol char */
+         goto recycle;
        default:
          BAD_CASE (state);
        }
@@ -501,12 +504,17 @@ recycle:
        {
          if (ch2 != EOF)
            (*unget) (ch2);
+         if (state == 9 || state == 10)
+           state = 3;
          return ch;
        }
       break;
 
     case LEX_IS_STRINGQUOTE:
-      old_state = state;
+      if (state == 9 || state == 10)
+       old_state = 3;
+      else
+       old_state = state;
       state = 5;
       return ch;
 #ifndef MRI
@@ -526,8 +534,7 @@ recycle:
       sprintf (out_buf, "%d", (int) (unsigned char) ch);
 
 
-      /* None of these 'x constants for us.  We want 'x'.
-                */
+      /* None of these 'x constants for us.  We want 'x'.  */
       if ((ch = (*get) ()) != '\'')
        {
 #ifdef REQUIRE_CHAR_CLOSE_QUOTE
@@ -540,14 +547,19 @@ recycle:
        {
          return out_buf[0];
        }
-      old_state = state;
+      if (state == 9 || state == 10)
+       old_state = 3;
+      else
+       old_state = state;
       state = -1;
       out_string = out_buf;
       return *out_string++;
 #endif
 #endif
     case LEX_IS_COLON:
-      if (state != 3)
+      if (state == 9 || state == 10)
+       state = 3;
+      else if (state != 3)
        state = 0;
       return ch;
 
@@ -565,53 +577,58 @@ recycle:
       return ch;
 
     case LEX_IS_LINE_COMMENT_START:
-      if (state != 0)          /* Not at start of line, act normal */
-       goto de_fault;
-
-      /* FIXME-someday: The two character comment stuff was badly
-        thought out.  On i386, we want '/' as line comment start AND
-        we want C style comments.  hence this hack.  The whole
-        lexical process should be reworked.  xoxorich.  */
-
-      if (ch == '/')
+      if (state == 0)          /* Only comment at start of line.  */
        {
-         ch2 = (*get) ();
-         if (ch2 == '*')
-           {
-             state = -2;
-             return (do_scrub_next_char (get, unget));
-           }
-         else
+         /* FIXME-someday: The two character comment stuff was badly
+            thought out.  On i386, we want '/' as line comment start
+            AND we want C style comments.  hence this hack.  The
+            whole lexical process should be reworked.  xoxorich.  */
+         if (ch == '/')
            {
-             (*unget) (ch2);
-           }
-       }                       /* bad hack */
+             ch2 = (*get) ();
+             if (ch2 == '*')
+               {
+                 state = -2;
+                 return (do_scrub_next_char (get, unget));
+               }
+             else
+               {
+                 (*unget) (ch2);
+               }
+           }                   /* bad hack */
 
-      do
-       ch = (*get) ();
-      while (ch != EOF && IS_WHITESPACE (ch));
-      if (ch == EOF)
-       {
-         as_warn ("EOF in comment:  Newline inserted");
-         return '\n';
-       }
-      if (ch < '0' || ch > '9')
-       {
-         /* Non-numerics:  Eat whole comment line */
-         while (ch != EOF && !IS_NEWLINE (ch))
+         do
            ch = (*get) ();
+         while (ch != EOF && IS_WHITESPACE (ch));
          if (ch == EOF)
-           as_warn ("EOF in Comment: Newline inserted");
-         state = 0;
-         return '\n';
+           {
+             as_warn ("EOF in comment:  Newline inserted");
+             return '\n';
+           }
+         if (ch < '0' || ch > '9')
+           {
+             /* Non-numerics:  Eat whole comment line */
+             while (ch != EOF && !IS_NEWLINE (ch))
+               ch = (*get) ();
+             if (ch == EOF)
+               as_warn ("EOF in Comment: Newline inserted");
+             state = 0;
+             return '\n';
+           }
+         /* Numerics begin comment.  Perhaps CPP `# 123 "filename"' */
+         (*unget) (ch);
+         old_state = 4;
+         state = -1;
+         out_string = ".appline ";
+         return *out_string++;
        }
-      /* Numerics begin comment.  Perhaps CPP `# 123 "filename"' */
-      (*unget) (ch);
-      old_state = 4;
-      state = -1;
-      out_string = ".line ";
-      return *out_string++;
 
+      /* We have a line comment character which is not at the start of
+        a line.  If this is also a normal comment character, fall
+        through.  Otherwise treat it as a default character.  */
+      if (strchr (comment_chars, ch) == NULL)
+       goto de_fault;
+      /* Fall through.  */
     case LEX_IS_COMMENT_START:
       do
        ch = (*get) ();
@@ -622,6 +639,15 @@ recycle:
       return '\n';
 
     case LEX_IS_SYMBOL_COMPONENT:
+      if (state == 10)
+       {
+         /* This is a symbol character following another symbol
+            character, with whitespace in between.  We skipped the
+            whitespace earlier, so output it now.  */
+         (*unget) (ch);
+         state = 3;
+         return ' ';
+       }
       if (state == 3)
        state = 9;
       /* Fall through.  */
@@ -644,6 +670,11 @@ recycle:
            state = 3;
          return ch;
        }
+      else if (state == 10)
+       {
+         state = 3;
+         return ch;
+       }
       else
        {
          return ch;            /* Opcode or operands already */
@@ -675,11 +706,4 @@ as_warn (str)
 
 #endif
 
-/*
- * Local Variables:
- * comment-column: 0
- * fill-column: 131
- * End:
- */
-
 /* end of app.c */
index 36e9fdc..d5282fa 100644 (file)
@@ -142,7 +142,7 @@ static void EXFUN( obj_coff_bss,(void));
 static void EXFUN( obj_coff_ident,(void));
 static void EXFUN (obj_coff_endef, (void));
 static void EXFUN (obj_coff_line, (void));
-static void EXFUN (obj_coff_ln, (void));
+static void EXFUN (obj_coff_ln, (int));
 static void EXFUN (obj_coff_scl, (void));
 static void EXFUN (obj_coff_size, (void));
 static void EXFUN (obj_coff_tag, (void));
@@ -163,6 +163,7 @@ const pseudo_typeS obj_pseudo_table[] =
   {"endef", obj_coff_endef, 0},
   {"line", obj_coff_line, 0},
   {"ln", obj_coff_ln, 0},
+  {"appline", obj_coff_ln, 1},
   {"scl", obj_coff_scl, 0},
   {"size", obj_coff_size, 0},
   {"tag", obj_coff_tag, 0},
@@ -776,11 +777,12 @@ stack_top (st)
  */
 
 static void
-obj_coff_ln ()
+obj_coff_ln (appline)
+     int appline;
 {
   int l;
 
-  if (def_symbol_in_progress != NULL)
+  if (! appline && def_symbol_in_progress != NULL)
     {
       as_warn (".ln pseudo-op inside .def/.endef: ignored.");
       demand_empty_rest_of_line ();
@@ -797,7 +799,9 @@ obj_coff_ln ()
 
     if (listing)
       {
-       listing_source_line (l + line_base - 1);
+       if (! appline)
+         l += line_base - 1;
+       listing_source_line (l);
       }
 
   }
@@ -1095,7 +1099,7 @@ obj_coff_line ()
 
   if (def_symbol_in_progress == NULL)
     {
-      obj_coff_ln ();
+      obj_coff_ln (0);
       return;
     }                          /* if it looks like a stabs style line */
 
index 3a853f2..6a5e79f 100644 (file)
@@ -405,12 +405,27 @@ gp_reference (ep)
 {
 #ifdef OBJ_ECOFF
   symbolS *sym;
+  const char *symname;
   const char *segname;
 
   sym = ep->X_add_symbol;
   if (sym == (symbolS *) NULL
       || ep->X_subtract_symbol != (symbolS *) NULL)
     return 0;
+
+  /* Certain symbols can not be referenced off the GP, although it
+     appears as though they can.  */
+  symname = S_GET_NAME (sym);
+  if (symname != (const char *) NULL
+      && (strcmp (symname, "eprol") == 0
+         || strcmp (symname, "etext") == 0
+         || strcmp (symname, "_gp") == 0
+         || strcmp (symname, "edata") == 0
+         || strcmp (symname, "_fbss") == 0
+         || strcmp (symname, "_fdata") == 0
+         || strcmp (symname, "_ftext") == 0
+         || strcmp (symname, "end") == 0))
+    return 0;
   if (! S_IS_DEFINED (sym)
       && S_GET_VALUE (sym) != 0
       && S_GET_VALUE (sym) <= g_switch_value)
@@ -883,13 +898,28 @@ macro (ip)
          macro_build (&icnt, &offset_expr, "bgez", "s,p", sreg);
          return;
        }
+      if (sreg == 0)
+       {
+         macro_build (&icnt, &offset_expr, "blez", "s,p", treg);
+         return;
+       }
       macro_build (&icnt, NULL, "slt", "d,v,t", AT, sreg, treg);
       macro_build (&icnt, &offset_expr, "beq", "s,t,p", AT, 0);
       break;
 
     case M_BGT_I:
+      /* check for > max integer */
+      if (imm_expr.X_add_number == 0x7fffffff)
+       {
+       do_false:
+         /* result is always false */
+         as_warn ("Branch %s is always false (nop)", ip->insn_mo->name);
+         macro_build (&icnt, NULL, "nop", "", 0);
+         return;
+       }
       imm_expr.X_add_number++;
       /* FALLTHROUGH */
+
     case M_BGE_I:
       if (imm_expr.X_add_number == 0)
        {
@@ -901,26 +931,39 @@ macro (ip)
          macro_build (&icnt, &offset_expr, "bgtz", "s,p", sreg);
          return;
        }
+      if (imm_expr.X_add_number == 0x80000000)
+       {
+       do_true:
+         /* result is always true */
+         as_warn ("Branch %s is always true", ip->insn_mo->name);
+         macro_build (&icnt, &offset_expr, "b", "p");
+         return;
+       }
       set_at (&icnt, sreg);
       macro_build (&icnt, &offset_expr, "beq", "s,t,p", AT, 0);
       break;
 
     case M_BGEU:
       if (treg == 0)
+       goto do_true;
+      if (sreg == 0)
        {
-         macro_build (&icnt, &offset_expr, "b", "p");
+         macro_build (&icnt, &offset_expr, "beq", "s,t,p", 0, treg);
          return;
        }
       macro_build (&icnt, NULL, "sltu", "d,v,t", AT, sreg, treg);
       macro_build (&icnt, &offset_expr, "beq", "s,t,p", AT, 0);
       break;
 
+    case M_BGTU_I:
+      if (sreg == 0 || imm_expr.X_add_number == 0xffffffff)
+       goto do_false;
+      imm_expr.X_add_number++;
+      /* FALLTHROUGH */
+
     case M_BGEU_I:
       if (imm_expr.X_add_number == 0)
-       {
-         macro_build (&icnt, &offset_expr, "b", "p");
-         return;
-       }
+       goto do_true;
       if (imm_expr.X_add_number == 1)
        {
          macro_build (&icnt, &offset_expr, "bne", "s,t,p", sreg, 0);
@@ -936,6 +979,11 @@ macro (ip)
          macro_build (&icnt, &offset_expr, "bgtz", "s,p", sreg);
          return;
        }
+      if (sreg == 0)
+       {
+         macro_build (&icnt, &offset_expr, "bltz", "s,p", treg);
+         return;
+       }
       macro_build (&icnt, NULL, "slt", "d,v,t", AT, treg, sreg);
       macro_build (&icnt, &offset_expr, "bne", "s,t,p", AT, 0);
       break;
@@ -946,50 +994,44 @@ macro (ip)
          macro_build (&icnt, &offset_expr, "bne", "s,t,p", sreg, 0);
          return;
        }
+      if (sreg == 0)
+       goto do_false;
       macro_build (&icnt, NULL, "sltu", "d,v,t", AT, treg, sreg);
       macro_build (&icnt, &offset_expr, "bne", "s,t,p", AT, 0);
       break;
 
-    case M_BGTU_I:
-      if (imm_expr.X_add_number == 0)
-       {
-         macro_build (&icnt, &offset_expr, "bne", "s,t,p", sreg, 0);
-         return;
-       }
-      if (imm_expr.X_add_number == -1)
-       {
-         /* NOP */
-         if (mips_noreorder)
-           as_warn ("Instruction %s is a nop; deleted", ip->insn_mo->name);
-         return;
-       }
-      imm_expr.X_add_number++;
-      set_at_unsigned (&icnt, sreg);
-      macro_build (&icnt, &offset_expr, "beq", "s,t,p", AT, 0);
-      break;
-
     case M_BLE:
       if (treg == 0)
        {
          macro_build (&icnt, &offset_expr, "blez", "s,p", sreg);
          return;
        }
+      if (sreg == 0)
+       {
+         macro_build (&icnt, &offset_expr, "bgez", "s,p", treg);
+         return;
+       }
       macro_build (&icnt, NULL, "slt", "d,v,t", AT, treg, sreg);
       macro_build (&icnt, &offset_expr, "beq", "s,t,p", AT, 0);
       break;
 
     case M_BLE_I:
+      if (imm_expr.X_add_number == 0x7fffffff)
+       goto do_true;
+      imm_expr.X_add_number++;
+      /* FALLTHROUGH */
+
+    case M_BLT_I:
       if (imm_expr.X_add_number == 0)
        {
-         macro_build (&icnt, &offset_expr, "blez", "s,p", sreg);
+         macro_build (&icnt, &offset_expr, "bltz", "s,p", sreg);
          return;
        }
-      if (imm_expr.X_add_number == -1)
+      if (imm_expr.X_add_number == 1)
        {
-         macro_build (&icnt, &offset_expr, "bltz", "s,p", sreg);
+         macro_build (&icnt, &offset_expr, "blez", "s,p", sreg);
          return;
        }
-      imm_expr.X_add_number++;
       set_at (&icnt, sreg);
       macro_build (&icnt, &offset_expr, "bne", "s,t,p", AT, 0);
       break;
@@ -1000,22 +1042,26 @@ macro (ip)
          macro_build (&icnt, &offset_expr, "beq", "s,t,p", sreg, 0);
          return;
        }
+      if (sreg == 0)
+       goto do_true;
       macro_build (&icnt, NULL, "sltu", "d,v,t", AT, treg, sreg);
       macro_build (&icnt, &offset_expr, "beq", "s,t,p", AT, 0);
       break;
 
     case M_BLEU_I:
+      if (sreg == 0 || imm_expr.X_add_number == 0xffffffff)
+       goto do_true;
+      imm_expr.X_add_number++;
+      /* FALLTHROUGH */
+
+    case M_BLTU_I:
       if (imm_expr.X_add_number == 0)
+       goto do_false;
+      if (imm_expr.X_add_number == 1)
        {
          macro_build (&icnt, &offset_expr, "beq", "s,t,p", sreg, 0);
          return;
        }
-      if (imm_expr.X_add_number == -1)
-       {
-         macro_build (&icnt, &offset_expr, "b", "p");
-         return;
-       }
-      imm_expr.X_add_number++;
       set_at_unsigned (&icnt, sreg);
       macro_build (&icnt, &offset_expr, "bne", "s,t,p", AT, 0);
       break;
@@ -1026,54 +1072,27 @@ macro (ip)
          macro_build (&icnt, &offset_expr, "bltz", "s,p", sreg);
          return;
        }
-      macro_build (&icnt, NULL, "slt", "d,v,t", AT, sreg, treg);
-      macro_build (&icnt, &offset_expr, "bne", "s,t,p", AT, 0);
-      break;
-
-    case M_BLT_I:
-      if (imm_expr.X_add_number == 0)
-       {
-         macro_build (&icnt, &offset_expr, "bltz", "s,p", sreg);
-         return;
-       }
-      if (imm_expr.X_add_number == 1)
+      if (sreg == 0)
        {
-         macro_build (&icnt, &offset_expr, "blez", "s,p", sreg);
+         macro_build (&icnt, &offset_expr, "bgtz", "s,p", treg);
          return;
        }
-      set_at (&icnt, sreg);
+      macro_build (&icnt, NULL, "slt", "d,v,t", AT, sreg, treg);
       macro_build (&icnt, &offset_expr, "bne", "s,t,p", AT, 0);
       break;
 
     case M_BLTU:
       if (treg == 0)
+       goto do_false;
+      if (sreg == 0)
        {
-         /* NOP */
-         if (mips_noreorder)
-           as_warn ("Instruction %s is a nop; deleted", ip->insn_mo->name);
+         macro_build (&icnt, &offset_expr, "bne", "s,t,p", 0, treg);
          return;
        }
       macro_build (&icnt, NULL, "sltu", "d,v,t", AT, sreg, treg);
       macro_build (&icnt, &offset_expr, "bne", "s,t,p", AT, 0);
       break;
 
-    case M_BLTU_I:
-      if (imm_expr.X_add_number == 0)
-       {
-         /* NOP */
-         if (mips_noreorder)
-           as_warn ("Instruction %s is a nop; deleted", ip->insn_mo->name);
-         return;
-       }
-      if (imm_expr.X_add_number == 1)
-       {
-         macro_build (&icnt, &offset_expr, "beq", "s,t,p", sreg, 0);
-         return;
-       }
-      set_at_unsigned (&icnt, sreg);
-      macro_build (&icnt, &offset_expr, "bne", "s,t,p", AT, 0);
-      break;
-
     case M_DIV_3:
     case M_REM_3:
       if (treg == 0)
@@ -1318,13 +1337,19 @@ macro (ip)
       break;
 
     case M_L_DOB:
+      /* Even on a big endian machine $fn comes before $fn+1.  We have
+        to adjust when loading from memory.  */
       save_reorder_condition = mips_noreorder;
       mips_noreorder = 1;
-      macro_build (&icnt, &offset_expr, "lwc1", "T,o(b)", treg, breg);
+      macro_build (&icnt, &offset_expr, "lwc1", "T,o(b)",
+                  byte_order == LITTLE_ENDIAN ? treg : treg + 1,
+                  breg);
       /* unecessary implicit nop */
       mips_noreorder = save_reorder_condition;
       offset_expr.X_add_number += 4;
-      macro_build (&icnt, &offset_expr, "lwc1", "T,o(b)", treg + 1, breg);
+      macro_build (&icnt, &offset_expr, "lwc1", "T,o(b)",
+                  byte_order == LITTLE_ENDIAN ? treg + 1 : treg,
+                  breg);
       return;
 
     case M_L_DAB:
@@ -1356,13 +1381,19 @@ macro (ip)
            macro_build (&icnt, NULL, "addu", "d,v,t", AT, AT, breg);
          tempreg = AT;
        }
+      /* Even on a big endian machine $fn comes before $fn+1.  We have
+        to adjust when loading from memory.  */
       save_reorder_condition = mips_noreorder;
       mips_noreorder = 1;
-      macro_build (&icnt, &offset_expr, "lwc1", "T,o(b)", treg, tempreg);
+      macro_build (&icnt, &offset_expr, "lwc1", "T,o(b)",
+                  byte_order == LITTLE_ENDIAN ? treg : treg + 1,
+                  tempreg);
       /* unecessary implicit nop */
       mips_noreorder = save_reorder_condition;
       offset_expr.X_add_number += 4;
-      macro_build (&icnt, &offset_expr, "lwc1", "T,o(b)", treg + 1, tempreg);
+      macro_build (&icnt, &offset_expr, "lwc1", "T,o(b)",
+                  byte_order == LITTLE_ENDIAN ? treg + 1 : treg,
+                  tempreg);
       if (tempreg == AT)
        break;
       return;
@@ -1469,9 +1500,15 @@ macro (ip)
       break;
 
     case M_S_DOB:
-      macro_build (&icnt, &offset_expr, "swc1", "T,o(b)", treg, breg);
+      /* Even on a big endian machine $fn comes before $fn+1.  We have
+        to adjust when storing to memory.  */
+      macro_build (&icnt, &offset_expr, "swc1", "T,o(b)",
+                  byte_order == LITTLE_ENDIAN ? treg : treg + 1,
+                  breg);
       offset_expr.X_add_number += 4;
-      macro_build (&icnt, &offset_expr, "swc1", "T,o(b)", treg + 1, breg);
+      macro_build (&icnt, &offset_expr, "swc1", "T,o(b)",
+                  byte_order == LITTLE_ENDIAN ? treg + 1 : treg,
+                  breg);
       return;
 
     case M_S_DAB:
@@ -1493,9 +1530,15 @@ macro (ip)
            macro_build (&icnt, NULL, "addu", "d,v,t", AT, AT, breg);
          tempreg = AT;
        }
-      macro_build (&icnt, &offset_expr, "swc1", "T,o(b)", treg, tempreg);
+      /* Even on a big endian machine $fn comes before $fn+1.  We have
+        to adjust when storing to memory.  */
+      macro_build (&icnt, &offset_expr, "swc1", "T,o(b)",
+                  byte_order == LITTLE_ENDIAN ? treg : treg + 1,
+                  tempreg);
       offset_expr.X_add_number += 4;
-      macro_build (&icnt, &offset_expr, "swc1", "T,o(b)", treg + 1, tempreg);
+      macro_build (&icnt, &offset_expr, "swc1", "T,o(b)",
+                  byte_order == LITTLE_ENDIAN ? treg + 1 : treg,
+                  tempreg);
       if (tempreg == AT)
        break;
       return;
@@ -1520,7 +1563,8 @@ macro (ip)
        }
       if (sreg == 0)
        {
-         /* result is always false */
+         as_warn ("Instruction %s: result is always false",
+           ip->insn_mo->name);
          macro_build (&icnt, NULL, "move", "d,s", dreg, 0);
          return;
        }
@@ -1610,7 +1654,7 @@ macro (ip)
       s = "sltu";
     sle:
       macro_build (&icnt, NULL, s, "d,v,t", dreg, treg, sreg);
-      macro_build (&icnt, &imm_expr, "xori", "t,r,i", dreg, dreg);
+      macro_build (&icnt, &expr1, "xori", "t,r,i", dreg, dreg);
       return;
 
     case M_SLE_I:              /* sreg <= I <==> I >= sreg <==> not (I < sreg) */
@@ -1621,7 +1665,7 @@ macro (ip)
     slei:
       load_register (&icnt, ip, AT, &imm_expr);
       macro_build (&icnt, NULL, s, "d,v,t", dreg, AT, sreg);
-      macro_build (&icnt, &offset_expr, "xori", "t,r,i", dreg, dreg);
+      macro_build (&icnt, &expr1, "xori", "t,r,i", dreg, dreg);
       break;
 
     case M_SLT_I:
@@ -1664,7 +1708,8 @@ macro (ip)
        }
       if (sreg == 0)
        {
-         /* result is always true */
+         as_warn ("Instruction %s: result is always true",
+           ip->insn_mo->name);
          macro_build (&icnt, &expr1, "addiu", "t,r,j", dreg, 0);
          return;
        }
@@ -3163,7 +3208,7 @@ s_file (x)
   int line;
 
   line = get_number ();
-  s_app_file ();
+  s_app_file (0);
 }
 
 
index 2b450a6..78061ef 100644 (file)
@@ -27,6 +27,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
 #define MASK_CHAR ((int)(unsigned char)-1)
 #endif
 
+
 /* This is the largest known floating point format (for now). It will
    grow when we do 4361 style flonums. */
 
@@ -44,6 +45,12 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
 #endif
 
 #include "obstack.h"
+#include "listing.h"
+
+
+#ifndef TC_START_LABEL
+#define TC_START_LABEL(x,y) (x==':')
+#endif
 
 /* The NOP_OPCODE is for the alignment fill value.
  * fill it a nop instruction so that the disassembler does not choke
@@ -195,7 +202,8 @@ static const pseudo_typeS potable[] =
 /* err */
 /* extend */
   {"extern", s_ignore, 0},     /* We treat all undef as ext */
-  {"appfile", s_app_file, 0},
+  {"appfile", s_app_file, 1},
+  {"appline", s_app_line, 0},
   {"file", s_app_file, 0},
   {"fill", s_fill, 0},
   {"float", float_cons, 'f'},
@@ -405,7 +413,7 @@ read_a_source_file (name)
               *   [In case of pseudo-op, s->'.'.]
               * Input_line_pointer->'\0' where c was.
               */
-             if (c == ':')
+             if (TC_START_LABEL(c, input_line_pointer))
                {
                  colon (s);    /* user-defined label */
                  *input_line_pointer++ = ':';  /* Put ':' back for error messages' sake. */
@@ -828,8 +836,16 @@ s_data ()
   demand_empty_rest_of_line ();
 }
 
+/* Handle the .appfile pseudo-op.  This is automatically generated by
+   do_scrub_next_char when a preprocessor # line comment is seen with
+   a file name.  This default definition may be overridden by the
+   object or CPU specific pseudo-ops.  This function is also the
+   default definition for .file; the APPFILE argument is 1 for
+   .appfile, 0 for .file.  */
+
 void 
-s_app_file ()
+s_app_file (appfile)
+     int appfile;
 {
   register char *s;
   int length;
@@ -837,14 +853,41 @@ s_app_file ()
   /* Some assemblers tolerate immediately following '"' */
   if ((s = demand_copy_string (&length)) != 0)
     {
-      new_logical_line (s, -1);
+      /* If this is a fake .appfile, a fake newline was inserted into
+        the buffer.  Passing -2 to new_logical_line tells it to
+        account for it.  */
+      new_logical_line (s, appfile ? -2 : -1);
       demand_empty_rest_of_line ();
+#ifdef LISTING
+      if (listing)
+       listing_source_file (s);
+#endif
     }
 #ifdef OBJ_COFF
   c_dot_file_symbol (s);
 #endif /* OBJ_COFF */
 }                              /* s_app_file() */
 
+/* Handle the .appline pseudo-op.  This is automatically generated by
+   do_scrub_next_char when a preprocessor # line comment is seen.
+   This default definition may be overridden by the object or CPU
+   specific pseudo-ops.  */
+
+void
+s_app_line ()
+{
+  int l;
+
+  /* The given number is that of the next line.  */
+  l = get_absolute_expression () - 1;
+  new_logical_line ((char *) NULL, l);
+#ifdef LISTING
+  if (listing)
+    listing_source_line (l);
+#endif
+  demand_empty_rest_of_line ();
+}
+
 void 
 s_fill ()
 {
@@ -943,8 +986,11 @@ s_lcomm (needs_align)
   register char *p;
   register int temp;
   register symbolS *symbolP;
+  segT current_seg = now_seg;
+  subsegT current_subseg = now_subseg;
   const int max_alignment = 15;
   int align = 0;
+  segT bss_seg = bss_section;
 
   name = input_line_pointer;
   c = get_symbol_end ();
@@ -973,6 +1019,14 @@ s_lcomm (needs_align)
       return;
     }
 
+#ifdef TC_MIPS
+#ifdef OBJ_ECOFF
+  /* For MIPS ECOFF, small objects are put in .sbss.  */
+  if (temp <= bfd_get_gp_size (stdoutput))
+    bss_seg = subseg_new (".sbss", 1);
+#endif
+#endif
+
   if (needs_align)
     {
       align = 0;
@@ -1001,7 +1055,7 @@ s_lcomm (needs_align)
          align = 0;
          as_warn ("Alignment negative. 0 assumed.");
        }
-      record_alignment (bss_section, align);
+      record_alignment (bss_seg, align);
     }                          /* if needs align */
 
   *p = 0;
@@ -1013,23 +1067,21 @@ s_lcomm (needs_align)
        S_GET_OTHER (symbolP) == 0 &&
        S_GET_DESC (symbolP) == 0 &&
 #endif /* OBJ_AOUT or OBJ_BOUT */
-       (S_GET_SEGMENT (symbolP) == bss_section
+       (S_GET_SEGMENT (symbolP) == bss_seg
        || (!S_IS_DEFINED (symbolP) && S_GET_VALUE (symbolP) == 0)))
     {
       char *p;
-      segT current_seg = now_seg;
-      subsegT current_subseg = now_subseg;
 
 #ifdef BFD_ASSEMBLER
-      subseg_set (bss_section, 1);
+      subseg_set (bss_seg, 1);
 #else
-      subseg_new (bss_section, 1);
+      subseg_new (bss_seg, 1);
 #endif
 
       if (align)
        frag_align (align, 0);
                                        /* detach from old frag */
-      if (S_GET_SEGMENT (symbolP) == bss_section)
+      if (S_GET_SEGMENT (symbolP) == bss_seg)
        symbolP->sy_frag->fr_symbol = NULL;
 
       symbolP->sy_frag = frag_now;
@@ -1037,7 +1089,7 @@ s_lcomm (needs_align)
                    temp, (char *)0);
       *p = 0;
 
-      S_SET_SEGMENT (symbolP, bss_section);
+      S_SET_SEGMENT (symbolP, bss_seg);
 
 #ifdef OBJ_COFF
       /* The symbol may already have been created with a preceding
@@ -1048,19 +1100,19 @@ s_lcomm (needs_align)
          S_SET_STORAGE_CLASS (symbolP, C_STAT);
        }
 #endif /* OBJ_COFF */
-#ifdef BFD_ASSEMBLER
-      subseg_set (current_seg, current_subseg);
-#else
-      subseg_new (current_seg, current_subseg);
-#endif
     }
   else
     {
       as_bad ("Ignoring attempt to re-define symbol %s.", name);
     }
-  demand_empty_rest_of_line ();
 
-  return;
+#ifdef BFD_ASSEMBLER
+  subseg_set (current_seg, current_subseg);
+#else
+  subseg_new (current_seg, current_subseg);
+#endif
+
+  demand_empty_rest_of_line ();
 }                              /* s_lcomm() */
 
 void
@@ -1406,18 +1458,23 @@ pseudo_set (symbolP)
          && (S_GET_SEGMENT (exp.X_add_symbol) ==
              S_GET_SEGMENT (exp.X_subtract_symbol)))
        {
-         if (exp.X_add_symbol->sy_frag != exp.X_subtract_symbol->sy_frag)
+         if (exp.X_add_symbol->sy_frag == exp.X_subtract_symbol->sy_frag)
            {
-             as_bad ("Unknown expression: symbols %s and %s are in different frags.",
-                     S_GET_NAME (exp.X_add_symbol), S_GET_NAME (exp.X_subtract_symbol));
-             need_pass_2++;
+             exp.X_add_number += S_GET_VALUE (exp.X_add_symbol) -
+               S_GET_VALUE (exp.X_subtract_symbol);
+             goto abs;
            }
-         exp.X_add_number += S_GET_VALUE (exp.X_add_symbol) -
-           S_GET_VALUE (exp.X_subtract_symbol);
+         as_bad ("Invalid expression: separation between symbols `%s'",
+                 S_GET_NAME (exp.X_add_symbol));
+         as_bad (" and `%s' may not be constant",
+                 S_GET_NAME (exp.X_subtract_symbol));
+         need_pass_2++;
        }
       else
-       as_bad ("Complex expression. Absolute segment assumed.");
-      goto abs;
+       {
+         as_bad ("Complex expression. Absolute segment assumed.");
+         goto abs;
+       }
     }
   else if (segment == absolute_section)
     {
@@ -1785,6 +1842,7 @@ cons (nbytes)
            /* undefined_section, others */
            {
            defalt:
+             md_number_to_chars (p, (long) 0, nbytes);
 #ifdef BFD_ASSEMBLER
              fix_new (frag_now, p - frag_now->fr_literal, nbytes,
                       exp.X_add_symbol, exp.X_subtract_symbol,
@@ -2051,7 +2109,7 @@ float_cons (float_type)           /* Worker to do .float etc statements. */
       err = md_atof (float_type, temp, &length);
       know (length <= MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT);
       know (length > 0);
-      if (*err)
+      if (err && *err)
        {
          as_bad ("Bad floating literal: %s", err);
          ignore_rest_of_line ();