* config/tc-ppc.h (OBJ_XCOFF): Define if OBJ_COFF and not TE_PE.
authorIan Lance Taylor <ian@airs.com>
Wed, 27 Sep 1995 19:02:16 +0000 (19:02 +0000)
committerIan Lance Taylor <ian@airs.com>
Wed, 27 Sep 1995 19:02:16 +0000 (19:02 +0000)
Change OBJ_COFF checks to check OBJ_XCOFF instead.
(TARGET_FORMAT): Fully parenthesize.
(LEX_QM): Define if TE_PE.
* config/tc-ppc.c: Replace OBJ_COFF by OBJ_XCOFF throughout.
Remove checks of TE_PE within #ifdef OBJ_XCOFF sections.
(init_regtable): Make i unsigned.
(ppc_set_current_section): Rename from setCurrentSection.  Change
all callers.
(ppc_arch): Return after as_fatal to avoid gcc warning.
(md_assemble): Only declare reloc if OBJ_ELF.  Add default to
switch on fixups[i].reloc to avoid gcc warning.
(IMAGE_SGN_LNK_OTHER): Fix nested comment.
(ppc_pe_function): Don't call ppc_canonicalize_symbol_name.
(ppc_frob_symbol): Remove TE_PE section checks.
(md_estimate_size_before_relax): Return after abort to avoid gcc
warning.
(md_apply_fix3): Add BFD_RELOC_16_GOT_PCREL to switch.
* read.c (LEX_QM): Define as 0 if not defined.
(lex_type): Use LEX_QM for '?'.

gas/ChangeLog
gas/config/tc-ppc.c
gas/config/tc-ppc.h
gas/read.c

index 32dcd088993336491bef960e920eb713dfebdd17..f3257520107d9948da13841579929d981f6a29dc 100644 (file)
@@ -1,5 +1,26 @@
 Wed Sep 27 12:53:58 1995  Ian Lance Taylor  <ian@cygnus.com>
 
+       * config/tc-ppc.h (OBJ_XCOFF): Define if OBJ_COFF and not TE_PE.
+       Change OBJ_COFF checks to check OBJ_XCOFF instead.
+       (TARGET_FORMAT): Fully parenthesize.
+       (LEX_QM): Define if TE_PE.
+       * config/tc-ppc.c: Replace OBJ_COFF by OBJ_XCOFF throughout.
+       Remove checks of TE_PE within #ifdef OBJ_XCOFF sections.
+       (init_regtable): Make i unsigned.
+       (ppc_set_current_section): Rename from setCurrentSection.  Change
+       all callers.
+       (ppc_arch): Return after as_fatal to avoid gcc warning.
+       (md_assemble): Only declare reloc if OBJ_ELF.  Add default to
+       switch on fixups[i].reloc to avoid gcc warning.
+       (IMAGE_SGN_LNK_OTHER): Fix nested comment.
+       (ppc_pe_function): Don't call ppc_canonicalize_symbol_name.
+       (ppc_frob_symbol): Remove TE_PE section checks.
+       (md_estimate_size_before_relax): Return after abort to avoid gcc
+       warning.
+       (md_apply_fix3): Add BFD_RELOC_16_GOT_PCREL to switch.
+       * read.c (LEX_QM): Define as 0 if not defined.
+       (lex_type): Use LEX_QM for '?'.
+
        * configure.in: No need to check whether ${cpu_type} is powerpc;
        it never will be.
        * configure: Rebuild.
index 31bf3f8a6ec46517a976312cff5dada1184f4e7e..c5eaac8a439aac7c4bb2747985292f85fb5c7a62 100644 (file)
@@ -46,7 +46,7 @@ static void ppc_byte PARAMS ((int));
 static int ppc_is_toc_sym PARAMS ((symbolS *sym));
 static void ppc_tc PARAMS ((int));
 
-#ifdef OBJ_COFF
+#ifdef OBJ_XCOFF
 static void ppc_comm PARAMS ((int));
 static void ppc_bb PARAMS ((int));
 static void ppc_bf PARAMS ((int));
@@ -71,6 +71,7 @@ static void ppc_elf_validate_fix PARAMS ((fixS *, segT));
 #endif
 
 #ifdef TE_PE
+static void ppc_set_current_section PARAMS ((segT));
 static void ppc_previous PARAMS ((int));
 static void ppc_pdata PARAMS ((int));
 static void ppc_ydata PARAMS ((int));
@@ -82,11 +83,7 @@ static void ppc_pe_comm PARAMS ((int));
 static void ppc_pe_section PARAMS ((int));
 static void ppc_pe_section PARAMS ((int));
 static void ppc_pe_function PARAMS ((int));
-
-segT ydata_section, pdata_section, reldata_section, rdata_section;
-
 #endif
-
 \f
 /* Generic assembler global variables which must be defined by all
    targets.  */
@@ -116,31 +113,24 @@ const pseudo_typeS md_pseudo_table[] =
   /* Pseudo-ops which must be overridden.  */
   { "byte",    ppc_byte,       0 },
 
-#ifdef OBJ_COFF
+#ifdef OBJ_XCOFF
   /* Pseudo-ops specific to the RS/6000 XCOFF format.  Some of these
      legitimately belong in the obj-*.c file.  However, XCOFF is based
      on COFF, and is only implemented for the RS/6000.  We just use
      obj-coff.c, and add what we need here.  */
-#ifndef TE_PE
   { "comm",    ppc_comm,       0 },
   { "lcomm",   ppc_comm,       1 },
-  { "function",        ppc_function,   0 },
-#endif
-
   { "bb",      ppc_bb,         0 },
   { "bf",      ppc_bf,         0 },
   { "bi",      ppc_biei,       0 },
   { "bs",      ppc_bs,         0 },
-
-#ifndef TE_PE
   { "csect",   ppc_csect,      0 },
-#endif
-
   { "eb",      ppc_eb,         0 },
   { "ef",      ppc_ef,         0 },
   { "ei",      ppc_biei,       1 },
   { "es",      ppc_es,         0 },
   { "extern",  ppc_extern,     0 },
+  { "function",        ppc_function,   0 },
   { "lglobl",  ppc_lglobl,     0 },
   { "rename",  ppc_rename,     0 },
   { "stabx",   ppc_stabx,      0 },
@@ -365,7 +355,8 @@ insert_reg (regname, regnum)
 static void
 init_regtable ()
 {
-  int i;
+  unsigned int i;
+
   for (i = 0; i < REG_NAME_CNT && pre_defined_registers[i].name ; ++i)
     {
       insert_reg (pre_defined_registers[i].name, 
@@ -400,7 +391,7 @@ static boolean mrelocatable = false;
 static flagword ppc_flags = 0;
 #endif
 
-#ifdef OBJ_COFF
+#ifdef OBJ_XCOFF
 
 /* The RS/6000 assembler uses the .csect pseudo-op to generate code
    using a bunch of different sections.  These assembler sections,
@@ -423,18 +414,6 @@ static symbolS *ppc_data_csects;
 /* The current csect.  */
 static symbolS *ppc_current_csect;
 
-/* The current csect.  */
-static segT ppc_previous_section;
-static segT ppc_current_section;
-
-void setCurrentSection(new)
-     segT new;
-{
-  ppc_previous_section = ppc_current_section;
-  ppc_current_section = new;
-}
-
-
 /* The RS/6000 assembler uses a TOC which holds addresses of functions
    and variables.  Symbols are put in the TOC with the .tc pseudo-op.
    A special relocation is used when accessing TOC entries.  We handle
@@ -460,7 +439,19 @@ static asection *ppc_coff_debug_section;
 /* The size of the .debug section.  */
 static bfd_size_type ppc_debug_name_section_size;
 
-#endif /* OBJ_COFF */
+#endif /* OBJ_XCOFF */
+
+#ifdef TE_PE
+
+/* Various sections.  */
+
+static segT ydata_section, pdata_section, reldata_section, rdata_section;
+
+/* The current section.  */
+static segT ppc_previous_section;
+static segT ppc_current_section;
+
+#endif /* TE_PE */
 
 #ifdef OBJ_ELF
 symbolS *GOT_symbol;           /* Pre-defined "_GLOBAL_OFFSET_TABLE" */
@@ -641,7 +632,10 @@ ppc_arch ()
   else if ((ppc_cpu & PPC_OPCODE_POWER) != 0)
     return bfd_arch_rs6000;
   else
-    as_fatal ("Neither Power nor PowerPC opcodes were selected.");
+    {
+      as_fatal ("Neither Power nor PowerPC opcodes were selected.");
+      return bfd_arch_unknown;
+    }
 }
 
 /* This function is called when the assembler starts up.  It is called
@@ -726,7 +720,7 @@ md_begin ()
       target_big_endian = PPC_BIG_ENDIAN;
     }
 
-#ifdef OBJ_COFF
+#ifdef OBJ_XCOFF
   ppc_coff_debug_section = coff_section_from_bfd_index (stdoutput, N_DEBUG);
 
   /* Create dummy symbols to serve as initial csects.  This forces the
@@ -997,7 +991,9 @@ md_assemble (str)
   int fc;
   char *f;
   int i;
+#ifdef OBJ_ELF
   bfd_reloc_code_real_type reloc;
+#endif
 
   /* Get the opcode.  */
   for (s = str; *s != '\0' && ! isspace (*s); s++)
@@ -1206,6 +1202,7 @@ md_assemble (str)
 #ifdef OBJ_ELF
          /* Allow @HA, @L, @H on constants. */
          char *orig_str = str;
+
          if ((reloc = ppc_elf_suffix (&str)) != BFD_RELOC_UNUSED)
            switch (reloc)
              {
@@ -1348,6 +1345,8 @@ md_assemble (str)
            case BFD_RELOC_HI16_S:
              fixP->fx_no_overflow = 1;
              break;
+           default:
+             break;
            }
        }
       else
@@ -1499,7 +1498,7 @@ ppc_byte (ignore)
   demand_empty_rest_of_line ();
 }
 \f
-#ifdef OBJ_COFF
+#ifdef OBJ_XCOFF
 
 /* XCOFF specific pseudo-op handling.  */
 
@@ -2274,7 +2273,7 @@ ppc_toc (ignore)
   demand_empty_rest_of_line ();
 }
 
-#endif /* OBJ_COFF */
+#endif /* OBJ_XCOFF */
 \f
 /* The .tc pseudo-op.  This is used when generating either XCOFF or
    ELF.  This takes two or more arguments.
@@ -2292,7 +2291,7 @@ static void
 ppc_tc (ignore)
      int ignore;
 {
-#ifdef OBJ_COFF
+#ifdef OBJ_XCOFF
 
   /* Define the TOC symbol name.  */
   {
@@ -2346,7 +2345,7 @@ ppc_tc (ignore)
     ppc_frob_label (sym);
   }
 
-#else /* ! defined (OBJ_COFF) */
+#else /* ! defined (OBJ_XCOFF) */
 
   /* Skip the TOC symbol name.  */
   while (is_part_of_name (*input_line_pointer)
@@ -2360,7 +2359,7 @@ ppc_tc (ignore)
   frag_align (2, 0);
   record_alignment (now_seg, 2);
 
-#endif /* ! defined (OBJ_COFF) */
+#endif /* ! defined (OBJ_XCOFF) */
 
   if (*input_line_pointer != ',')
     demand_empty_rest_of_line ();
@@ -2370,7 +2369,6 @@ ppc_tc (ignore)
       cons (4);
     }
 }
-
 \f
 #ifdef TE_PE
 /* Pseudo-ops specific to the Windows NT PowerPC PE (coff) format */
@@ -2385,7 +2383,7 @@ ppc_tc (ignore)
 #define IMAGE_SCN_CNT_INITIALIZED_DATA       0x00000040  /* Section contains initialized data. */
 #define IMAGE_SCN_CNT_UNINITIALIZED_DATA     0x00000080  /* Section contains uninitialized data. */
 
-#define IMAGE_SCN_LNK_OTHER                  0x00000100  /* Reserved.
+#define IMAGE_SCN_LNK_OTHER                  0x00000100  /* Reserved.  */
 #define IMAGE_SCN_LNK_INFO                   0x00000200  /* Section contains comments or some other type of information. */
 #define IMAGE_SCN_LNK_REMOVE                 0x00000800  /* Section contents will not become part of image. */
 #define IMAGE_SCN_LNK_COMDAT                 0x00001000  /* Section contents comdat. */
@@ -2415,6 +2413,15 @@ ppc_tc (ignore)
 #define IMAGE_SCN_MEM_READ                   0x40000000  /* Section is readable.                   */
 #define IMAGE_SCN_MEM_WRITE                  0x80000000  /* Section is writeable.                  */
 
+/* Set the current section.  */
+
+static void
+ppc_set_current_section (new)
+     segT new;
+{
+  ppc_previous_section = ppc_current_section;
+  ppc_current_section = new;
+}
 
 /* pseudo-op: .previous
    behaviour: toggles the current section with the previous section.
@@ -2435,7 +2442,7 @@ ppc_previous(ignore)
 
   subseg_set(ppc_previous_section, 0);
 
-  setCurrentSection(ppc_previous_section);
+  ppc_set_current_section(ppc_previous_section);
 }
 
 /* pseudo-op: .pdata
@@ -2472,7 +2479,7 @@ ppc_pdata(ignore)
     {
       pdata_section = subseg_new(".pdata", 0);
     }
-  setCurrentSection(pdata_section);
+  ppc_set_current_section(pdata_section);
 }
 
 /* pseudo-op: .ydata
@@ -2506,7 +2513,7 @@ ppc_ydata(ignore)
     {
       ydata_section = subseg_new (".ydata", 0);
     }
-  setCurrentSection(ydata_section);
+  ppc_set_current_section(ydata_section);
 }
 
 /* pseudo-op: .reldata
@@ -2544,7 +2551,7 @@ ppc_reldata(ignore)
     {
       reldata_section = subseg_new (".reldata", 0);
     }
-  setCurrentSection(reldata_section);
+  ppc_set_current_section(reldata_section);
 }
 
 /* pseudo-op: .rdata
@@ -2574,7 +2581,7 @@ ppc_rdata(ignore)
     {
       rdata_section = subseg_new (".rdata", 0);
     }
-  setCurrentSection(rdata_section);
+  ppc_set_current_section(rdata_section);
 }
 
 /* pseudo-op: .ualong
@@ -2921,7 +2928,7 @@ ppc_pe_section (ignore)
 
   sec = subseg_new (name, (subsegT) exp);
 
-  setCurrentSection(sec);
+  ppc_set_current_section(sec);
 
   if (flags != SEC_NO_FLAGS)
     {
@@ -2953,20 +2960,11 @@ ppc_pe_function (ignore)
 {
   char *name;
   char endc;
-  char *s;
   symbolS *ext_sym;
-  symbolS *lab_sym;
 
   name = input_line_pointer;
   endc = get_symbol_end ();
 
-  /* Ignore any [PR] suffix.  */
-  name = ppc_canonicalize_symbol_name (name);
-  s = strchr (name, '[');
-  if (s != (char *) NULL
-      && strcmp (s + 1, "PR]") == 0)
-    *s = '\0';
-
   ext_sym = symbol_find_or_make (name);
 
   *input_line_pointer = endc;
@@ -2979,13 +2977,9 @@ ppc_pe_function (ignore)
   demand_empty_rest_of_line ();
 }
 
-
 #endif
-
-
-
 \f
-#ifdef OBJ_COFF
+#ifdef OBJ_XCOFF
 
 /* XCOFF specific symbol and file handling.  */
 
@@ -3116,7 +3110,6 @@ void
 ppc_frob_label (sym)
      symbolS *sym;
 {
-#ifndef TE_PE
   if (ppc_current_csect != (symbolS *) NULL)
     {
       if (sym->sy_tc.class == -1)
@@ -3127,7 +3120,6 @@ ppc_frob_label (sym)
                     &symbol_lastP);
       ppc_current_csect->sy_tc.within = sym;
     }
-#endif
 }
 
 /* Change the name of a symbol just before writing it out.  Set the
@@ -3207,7 +3199,6 @@ ppc_frob_symbol (sym)
        }
     }
 
-#ifndef TE_PE 
   if (! S_IS_EXTERNAL (sym)
       && (sym->bsym->flags & BSF_SECTION_SYM) == 0
       && S_GET_STORAGE_CLASS (sym) != C_FILE
@@ -3216,7 +3207,6 @@ ppc_frob_symbol (sym)
       && S_GET_STORAGE_CLASS (sym) != C_ESTAT
       && S_GET_SEGMENT (sym) != ppc_coff_debug_section)
     S_SET_STORAGE_CLASS (sym, C_HIDEXT);
-#endif
 
   if (S_GET_STORAGE_CLASS (sym) == C_EXT
       || S_GET_STORAGE_CLASS (sym) == C_HIDEXT)
@@ -3295,30 +3285,8 @@ ppc_frob_symbol (sym)
            }
          a->x_csect.x_smtyp = (2 << 3) | XTY_SD;
        }
-
-#ifdef TE_PE
-      else if (S_GET_SEGMENT (sym) == pdata_section) 
-       {
-         a->x_csect.x_scnlen.l = (bfd_section_size (stdoutput,
-                                                    S_GET_SEGMENT (sym))
-                                  - S_GET_VALUE (sym));
-       }
-      else if (S_GET_SEGMENT (sym) == rdata_section)
-       {
-         a->x_csect.x_scnlen.l = (bfd_section_size (stdoutput,
-                                                    S_GET_SEGMENT (sym))
-                                  - S_GET_VALUE (sym));
-       }
-      else if (S_GET_SEGMENT (sym) == reldata_section)
-       {
-         a->x_csect.x_scnlen.l = (bfd_section_size (stdoutput,
-                                                    S_GET_SEGMENT (sym))
-                                  - S_GET_VALUE (sym));
-       }
-#endif
       else
        {
-#ifndef TE_PE
          symbolS *csect;
 
          /* This is a normal symbol definition.  x_scnlen is the
@@ -3349,7 +3317,6 @@ ppc_frob_symbol (sym)
              coffsymbol (sym->bsym)->native[i + 1].fix_scnlen = 1;
            }
          a->x_csect.x_smtyp = XTY_LD;
-#endif
        }
        
       a->x_csect.x_parmhash = 0;
@@ -3392,12 +3359,10 @@ void
 ppc_frob_section (sec)
      asection *sec;
 {
-#ifndef TE_PE
   static bfd_size_type vma = 0;
 
   bfd_set_section_vma (stdoutput, sec, vma);
   vma += bfd_section_size (stdoutput, sec);
-#endif
 }
 
 /* Adjust the file by adding a .debug section if needed.  */
@@ -3419,7 +3384,7 @@ ppc_frob_file ()
     }
 }
 
-#endif /* OBJ_COFF */
+#endif /* OBJ_XCOFF */
 \f
 /* Turn a string in input_line_pointer into a floating point constant
    of type type, and store the appropriate bytes in *litp.  The number
@@ -3513,6 +3478,7 @@ md_estimate_size_before_relax (fragp, seg)
      asection *seg;
 {
   abort ();
+  return 0;
 }
 
 /* Convert a machine dependent frag.  We never generate these.  */
@@ -3555,7 +3521,7 @@ md_pcrel_from (fixp)
   return fixp->fx_frag->fr_address + fixp->fx_where;
 }
 
-#ifdef OBJ_COFF
+#ifdef OBJ_XCOFF
 
 /* This is called to see whether a fixup should be adjusted to use a
    section symbol.  We take the opportunity to change a fixup against
@@ -3568,12 +3534,6 @@ ppc_fix_adjustable (fix)
 {
   valueT val;
 
-#ifdef TE_PE
-  /* FIXME: Certainly the toc stuff gets us into trouble, and should
-            not be executed. Not sure about the reloc adjustments. */
-  return 0;
-#endif
-
   resolve_symbol_value (fix->fx_addsy);
   val = S_GET_VALUE (fix->fx_addsy);
   if (ppc_toc_csect != (symbolS *) NULL
@@ -3662,7 +3622,7 @@ static int
 ppc_is_toc_sym (sym)
      symbolS *sym;
 {
-#ifdef OBJ_COFF
+#ifdef OBJ_XCOFF
   return sym->sy_tc.class == XMC_TC;
 #else
   return strcmp (segment_name (S_GET_SEGMENT (sym)), ".got") == 0;
@@ -3731,7 +3691,7 @@ md_apply_fix3 (fixp, valuep, seg)
 
       operand = &powerpc_operands[opindex];
 
-#ifdef OBJ_COFF
+#ifdef OBJ_XCOFF
       /* It appears that an instruction like
             l 9,LC..1(30)
         when LC..1 is not a TOC symbol does not generate a reloc.  It
@@ -3842,6 +3802,7 @@ md_apply_fix3 (fixp, valuep, seg)
        case BFD_RELOC_PPC_TOC16:
        case BFD_RELOC_16:
        case BFD_RELOC_GPREL16:
+       case BFD_RELOC_16_GOT_PCREL:
          if (fixp->fx_pcrel)
            abort ();
 
index 9d46c24dd5a2ecffb04089b40158c59c2fe3ce66..1a456aed9ced55ecfd1f89b4bf44772cfd9d1e5a 100644 (file)
  #error PowerPC support requires BFD_ASSEMBLER
 #endif
 
+/* If OBJ_COFF is defined, and TE_PE is not defined, we are assembling
+   XCOFF for AIX.  If TE_PE is defined, we are assembling COFF for
+   Windows NT.  */
+
+#ifdef OBJ_COFF
+#ifndef TE_PE
+#define OBJ_XCOFF
+#endif
+#endif
+
 /* The target BFD architecture.  */
 #define TARGET_ARCH (ppc_arch ())
 extern enum bfd_architecture ppc_arch PARAMS ((void));
@@ -34,16 +44,14 @@ extern int target_big_endian;
 /* The target BFD format.  */
 #ifdef OBJ_COFF
 #ifdef TE_PE
-#define TARGET_FORMAT (target_big_endian) ? "pe-powerpc" : "pe-powerpcle"
-#elif defined(PPC)
-#define TARGET_FORMAT (target_big_endian) ? "coff-powerpc" : "coff-powerpcle"
+#define TARGET_FORMAT (target_big_endian ? "pe-powerpc" : "pe-powerpcle")
 #else
 #define TARGET_FORMAT "aixcoff-rs6000"
 #endif
 #endif
 
 #ifdef OBJ_ELF
-#define TARGET_FORMAT (target_big_endian) ? "elf32-powerpc" : "elf32-powerpcle"
+#define TARGET_FORMAT (target_big_endian ? "elf32-powerpc" : "elf32-powerpcle")
 #endif
 
 /* Permit temporary numeric labels.  */
@@ -59,7 +67,7 @@ extern int target_big_endian;
 
 /* When using COFF, we determine whether or not to output a symbol
    based on sy_tc.output, not on the name.  */
-#ifdef OBJ_COFF
+#ifdef OBJ_XCOFF
 #define LOCAL_LABEL(name) 0
 #endif
 #ifdef OBJ_ELF
@@ -89,7 +97,14 @@ extern int target_big_endian;
 /* We set the fx_done field appropriately in md_apply_fix.  */
 #define TC_HANDLES_FX_DONE
 \f
-#ifdef OBJ_COFF
+#ifdef TE_PE
+
+/* Question marks are permitted in symbol names.  */
+#define LEX_QM 1
+
+#endif
+
+#ifdef OBJ_XCOFF
 
 /* Declarations needed when generating XCOFF code.  XCOFF is an
    extension of COFF, used only on the RS/6000.  Rather than create an
@@ -162,7 +177,7 @@ extern int ppc_frob_symbol PARAMS ((struct symbol *));
 #define tc_frob_file() ppc_frob_file ()
 extern void ppc_frob_file PARAMS ((void));
 
-#endif /* OBJ_COFF */
+#endif /* OBJ_XCOFF */
 
 #ifdef OBJ_ELF
 /* The name of the global offset table generated by the compiler. Allow
index f7a4f55927c9e618ebfe8ffc1b0a8e1981627e90..40fd01f514fd6ffdf77a8e83fa16ebe14fd5a8f5 100644 (file)
@@ -85,13 +85,18 @@ die horribly;
 #define LEX_PCT 0
 #endif
 
+#ifndef LEX_QM
+/* The PowerPC Windows NT assemblers permits ? inside label names.  */
+#define LEX_QM 0
+#endif
+
 /* used by is_... macros. our ctype[] */
 char lex_type[256] =
 {
   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,      /* @ABCDEFGHIJKLMNO */
   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,      /* PQRSTUVWXYZ[\]^_ */
   0, 0, 0, 0, 3, LEX_PCT, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0,        /* _!"#$%&'()*+,-./ */
-  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,      /* 0123456789:;<=>? */
+  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, LEX_QM, /* 0123456789:;<=>? */
   LEX_AT, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* @ABCDEFGHIJKLMNO */
   3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, LEX_BR, 0, LEX_BR, 0, 3, /* PQRSTUVWXYZ[\]^_ */
   0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,      /* `abcdefghijklmno */
@@ -948,6 +953,48 @@ read_a_source_file (name)
   input_scrub_close ();                /* Close the input file */
 }
 
+/* For most MRI pseudo-ops, the line actually ends at the first
+   nonquoted space.  This function looks for that point, stuffs a null
+   in, and sets *STOPCP to the character that used to be there, and
+   returns the location.  */
+
+char *
+mri_comment_field (stopcp)
+     char *stopcp;
+{
+  char *s;
+  int inquote = 0;
+
+  know (flag_mri);
+
+  for (s = input_line_pointer;
+       ((! is_end_of_line[(unsigned char) *s] && *s != ' ' && *s != '\t')
+       || inquote);
+       s++)
+    {
+      if (*s == '\'')
+       inquote = ! inquote;
+    }
+  *stopcp = *s;
+  *s = '\0';
+  return s;
+}
+
+/* Skip to the end of an MRI comment field.  */
+
+void
+mri_comment_end (stop, stopc)
+     char *stop;
+     int stopc;
+{
+  know (flag_mri);
+
+  input_line_pointer = stop;
+  *stop = stopc;
+  while (! is_end_of_line[(unsigned char) *input_line_pointer])
+    ++input_line_pointer;
+}
+
 void 
 s_abort (ignore)
      int ignore;
@@ -999,6 +1046,11 @@ s_align_bytes (arg)
   char temp_fill;
   unsigned int i = 0;
   unsigned long max_alignment = 1 << 15;
+  char *stop = NULL;
+  char stopc;
+
+  if (flag_mri)
+    stop = mri_comment_field (&stopc);
 
   if (is_end_of_line[(unsigned char) *input_line_pointer])
     temp = arg;                        /* Default value from pseudo-op table */
@@ -1030,6 +1082,9 @@ s_align_bytes (arg)
   else
     do_align (temp, (char *) 0);
 
+  if (flag_mri)
+    mri_comment_end (stop, stopc);
+
   demand_empty_rest_of_line ();
 }
 
@@ -1041,6 +1096,11 @@ s_align_ptwo (ignore)
   register int temp;
   char temp_fill;
   long max_alignment = 15;
+  char *stop = NULL;
+  char stopc;
+
+  if (flag_mri)
+    stop = mri_comment_field (&stopc);
 
   temp = get_absolute_expression ();
   if (temp > max_alignment)
@@ -1059,6 +1119,9 @@ s_align_ptwo (ignore)
   else
     do_align (temp, (char *) 0);
 
+  if (flag_mri)
+    mri_comment_end (stop, stopc);
+
   demand_empty_rest_of_line ();
 }
 
@@ -1071,6 +1134,11 @@ s_comm (ignore)
   register char *p;
   offsetT temp;
   register symbolS *symbolP;
+  char *stop = NULL;
+  char stopc;
+
+  if (flag_mri)
+    stop = mri_comment_field (&stopc);
 
   name = input_line_pointer;
   c = get_symbol_end ();
@@ -1081,6 +1149,8 @@ s_comm (ignore)
   if (*input_line_pointer != ',')
     {
       as_bad ("Expected comma after symbol-name: rest of line ignored.");
+      if (flag_mri)
+       mri_comment_end (stop, stopc);
       ignore_rest_of_line ();
       return;
     }
@@ -1088,6 +1158,8 @@ s_comm (ignore)
   if ((temp = get_absolute_expression ()) < 0)
     {
       as_warn (".COMMon length (%ld.) <0! Ignored.", (long) temp);
+      if (flag_mri)
+       mri_comment_end (stop, stopc);
       ignore_rest_of_line ();
       return;
     }
@@ -1098,6 +1170,8 @@ s_comm (ignore)
     {
       as_bad ("Ignoring attempt to re-define symbol `%s'.",
              S_GET_NAME (symbolP));
+      if (flag_mri)
+       mri_comment_end (stop, stopc);
       ignore_rest_of_line ();
       return;
     }
@@ -1122,6 +1196,10 @@ s_comm (ignore)
   }
 #endif /* not OBJ_VMS */
   know (symbolP->sy_frag == &zero_address_frag);
+
+  if (flag_mri)
+    mri_comment_end (stop, stopc);
+
   demand_empty_rest_of_line ();
 }                              /* s_comm() */
 
@@ -1138,6 +1216,8 @@ s_mri_common (small)
   char *alc = NULL;
   symbolS *sym;
   offsetT align;
+  char *stop = NULL;
+  char stopc;
 
   if (! flag_mri)
     {
@@ -1145,6 +1225,8 @@ s_mri_common (small)
       return;
     }
 
+  stop = mri_comment_field (&stopc);
+
   SKIP_WHITESPACE ();
 
   name = input_line_pointer;
@@ -1190,6 +1272,7 @@ s_mri_common (small)
 #endif
        {
          as_bad ("attempt to re-define symbol `%s'", S_GET_NAME (sym));
+         mri_comment_end (stop, stopc);
          ignore_rest_of_line ();
          return;
        }
@@ -1220,6 +1303,9 @@ s_mri_common (small)
     input_line_pointer += 2;
   if (*input_line_pointer == ',')
     input_line_pointer += 2;
+
+  mri_comment_end (stop, stopc);
+
   demand_empty_rest_of_line ();
 }
 
@@ -1319,7 +1405,9 @@ s_end (ignore)
       /* 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])
+      if (! is_end_of_line[(unsigned char) *input_line_pointer]
+         && *input_line_pointer != '*'
+         && *input_line_pointer != '!')
        as_warn ("start address not supported");
     }
 }
@@ -1331,12 +1419,21 @@ s_fail (ignore)
      int ignore;
 {
   offsetT temp;
+  char *stop = NULL;
+  char stopc;
+
+  if (flag_mri)
+    stop = mri_comment_field (&stopc);
 
   temp = get_absolute_expression ();
   if (temp >= 500)
     as_warn (".fail %ld encountered", (long) temp);
   else
     as_bad (".fail %ld encountered", (long) temp);
+
+  if (flag_mri)
+    mri_comment_end (stop, stopc);
+
   demand_empty_rest_of_line ();
 }
 
@@ -1408,6 +1505,11 @@ s_globl (ignore)
   char *name;
   int c;
   symbolS *symbolP;
+  char *stop = NULL;
+  char stopc;
+
+  if (flag_mri)
+    stop = mri_comment_field (&stopc);
 
   do
     {
@@ -1426,6 +1528,10 @@ s_globl (ignore)
        }
     }
   while (c == ',');
+
+  if (flag_mri)
+    mri_comment_end (stop, stopc);
+
   demand_empty_rest_of_line ();
 }
 
@@ -2037,24 +2143,8 @@ s_space (mult)
   md_flush_pending_output ();
 #endif
 
-  /* In MRI mode, the operands end at the first unquoted space.  */
   if (flag_mri)
-    {
-      char *s;
-      int inquote = 0;
-
-      for (s = input_line_pointer;
-          ((! is_end_of_line[(unsigned char) *s] && *s != ' ' && *s != '\t')
-           || inquote);
-          s++)
-       {
-         if (*s == '\'')
-           inquote = ! inquote;
-       }
-      stop = s;
-      stopc = *stop;
-      *stop = '\0';
-    }
+    stop = mri_comment_field (&stopc);
 
   /* Just like .fill, but temp_size = 1 */
   expression (&exp);
@@ -2126,12 +2216,7 @@ s_space (mult)
 
  getout:
   if (flag_mri)
-    {
-      input_line_pointer = stop;
-      *stop = stopc;
-      while (! is_end_of_line[(unsigned char) *input_line_pointer])
-       ++input_line_pointer;
-    }
+    mri_comment_end (stop, stopc);
 
   demand_empty_rest_of_line ();
 }
@@ -2147,6 +2232,11 @@ s_float_space (float_type)
   offsetT count;
   int flen;
   char temp[MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT];
+  char *stop = NULL;
+  char stopc;
+
+  if (flag_mri)
+    stop = mri_comment_field (&stopc);
 
   count = get_absolute_expression ();
 
@@ -2154,6 +2244,8 @@ s_float_space (float_type)
   if (*input_line_pointer != ',')
     {
       as_bad ("missing value");
+      if (flag_mri)
+       mri_comment_end (stop, stopc);
       ignore_rest_of_line ();
       return;
     }
@@ -2174,6 +2266,8 @@ s_float_space (float_type)
       flen = hex_float (float_type, temp);
       if (flen < 0)
        {
+         if (flag_mri)
+           mri_comment_end (stop, stopc);
          ignore_rest_of_line ();
          return;
        }
@@ -2188,6 +2282,8 @@ s_float_space (float_type)
       if (err)
        {
          as_bad ("Bad floating literal: %s", err);
+         if (flag_mri)
+           mri_comment_end (stop, stopc);
          ignore_rest_of_line ();
          return;
        }
@@ -2201,6 +2297,9 @@ s_float_space (float_type)
       memcpy (p, temp, (unsigned int) flen);
     }
 
+  if (flag_mri)
+    mri_comment_end (stop, stopc);
+
   demand_empty_rest_of_line ();
 }
 
@@ -2210,8 +2309,15 @@ void
 s_struct (ignore)
      int ignore;
 {
+  char *stop = NULL;
+  char stopc;
+
+  if (flag_mri)
+    stop = mri_comment_field (&stopc);
   abs_section_offset = get_absolute_expression ();
   subseg_set (absolute_section, 0);
+  if (flag_mri)
+    mri_comment_end (stop, stopc);
   demand_empty_rest_of_line ();
 }
 
@@ -2428,31 +2534,16 @@ cons_worker (nbytes, rva)
   md_flush_pending_output ();
 #endif
 
+  if (flag_mri)
+    stop = mri_comment_field (&stopc);
+
   if (is_it_end_of_statement ())
     {
+      mri_comment_end (stop, stopc);
       demand_empty_rest_of_line ();
       return;
     }
 
-  /* In MRI mode, the operands end at the first unquoted space.  */
-  if (flag_mri)
-    {
-      char *s;
-      int inquote = 0;
-
-      for (s = input_line_pointer;
-          ((! is_end_of_line[(unsigned char) *s] && *s != ' ' && *s != '\t')
-           || inquote);
-          s++)
-       {
-         if (*s == '\'')
-           inquote = ! inquote;
-       }
-      stop = s;
-      stopc = *stop;
-      *stop = '\0';
-    }
-
   c = 0;
   do
     {
@@ -2484,8 +2575,7 @@ cons_worker (nbytes, rva)
        emit_expr (&exp, (unsigned int) nbytes);
       ++c;
     }
-  while (*input_line_pointer++ == ','
-        && (! flag_mri || input_line_pointer < stop));
+  while (*input_line_pointer++ == ',');
 
   /* In MRI mode, after an odd number of bytes, we must align to an
      even word boundary, unless the next instruction is a dc.b, ds.b
@@ -2496,12 +2586,7 @@ cons_worker (nbytes, rva)
   input_line_pointer--;                /* Put terminator back into stream. */
 
   if (flag_mri)
-    {
-      input_line_pointer = stop;
-      *stop = stopc;
-      while (! is_end_of_line[(unsigned char) *input_line_pointer])
-       ++input_line_pointer;
-    }
+    mri_comment_end (stop, stopc);
 
   demand_empty_rest_of_line ();
 }
@@ -3557,7 +3642,7 @@ equals (sym_name)
 {
   register symbolS *symbolP;   /* symbol we are working with */
   char *stop;
-  int stopc;
+  char stopc;
 
   input_line_pointer++;
   if (*input_line_pointer == '=')
@@ -3566,24 +3651,8 @@ equals (sym_name)
   while (*input_line_pointer == ' ' || *input_line_pointer == '\t')
     input_line_pointer++;
 
-  /* In MRI mode, the operands end at the first unquoted space.  */
   if (flag_mri)
-    {
-      char *s;
-      int inquote = 0;
-
-      for (s = input_line_pointer;
-          ((! is_end_of_line[(unsigned char) *s] && *s != ' ' && *s != '\t')
-           || inquote);
-          s++)
-       {
-         if (*s == '\'')
-           inquote = ! inquote;
-       }
-      stop = s;
-      stopc = *stop;
-      *stop = '\0';
-    }
+    stop = mri_comment_field (&stopc);
 
   if (sym_name[0] == '.' && sym_name[1] == '\0')
     {
@@ -3602,12 +3671,7 @@ equals (sym_name)
     }
 
   if (flag_mri)
-    {
-      input_line_pointer = stop;
-      *stop = stopc;
-      while (! is_end_of_line[(unsigned char) *input_line_pointer])
-       ++input_line_pointer;
-    }
+    mri_comment_end (stop, stopc);
 }                              /* equals() */
 
 /* .include -- include a file at this point. */