Sanitize support for the ESA sparc simulator.
[deliverable/binutils-gdb.git] / gas / config / tc-m68k.c
index 3cb8121ca7f02a0ad755b0d5d85b47fdae81fba6..cd70be1207d2784772dfb3335761e60977009330 100644 (file)
@@ -1,5 +1,5 @@
 /* tc-m68k.c -- Assemble for the m68k family
-   Copyright (C) 1987, 91, 92, 93, 94, 1995 Free Software Foundation, Inc.
+   Copyright (C) 1987, 91, 92, 93, 94, 95, 1996 Free Software Foundation, Inc.
 
    This file is part of GAS, the GNU Assembler.
 
@@ -19,7 +19,6 @@
    02111-1307, USA.  */
 
 #include <ctype.h>
-#define  NO_RELOC 0
 #include "as.h"
 #include "obstack.h"
 #include "subsegs.h"
 
 /* This array holds the chars that always start a comment.  If the
    pre-processor is disabled, these aren't very useful */
-#if defined (OBJ_ELF) || defined (TE_DELTA)
-CONST char comment_chars[] = "|#";
+#if (defined (OBJ_ELF) && ! defined (TE_PSOS) && ! defined (TE_LINUX)) || defined (TE_DELTA)
+const char comment_chars[] = "|#";
 #else
-CONST char comment_chars[] = "|";
+const char comment_chars[] = "|";
 #endif
 
 /* This array holds the chars that only start a comment at the beginning of
@@ -42,9 +41,9 @@ CONST char comment_chars[] = "|";
    first line of the input file.  This is because the compiler outputs
    #NO_APP at the beginning of its output. */
 /* Also note that comments like this one will always work. */
-CONST char line_comment_chars[] = "#";
+const char line_comment_chars[] = "#";
 
-CONST char line_separator_chars[] = "";
+const char line_separator_chars[] = "";
 
 /* Chars that can be used to separate mant from exp in floating point nums */
 CONST char EXP_CHARS[] = "eE";
@@ -62,7 +61,8 @@ const int md_reloc_size = 8;  /* Size of relocation record */
 
 /* Are we trying to generate PIC code?  If so, absolute references
    ought to be made into linkage table references or pc-relative
-   references.  */
+   references.  Not implemented.  For ELF there are other means 
+   to denote pic relocations.  */
 int flag_want_pic;
 
 static int flag_short_refs;    /* -l option */
@@ -74,6 +74,9 @@ int flag_reg_prefix_optional = REGISTER_PREFIX_OPTIONAL;
 int flag_reg_prefix_optional;
 #endif
 
+/* Whether --register-prefix-optional was used on the command line.  */
+static int reg_prefix_optional_seen;
+
 /* The floating point coprocessor to use by default.  */
 static enum m68k_register m68k_float_copnum = COP1;
 
@@ -199,6 +202,11 @@ struct m68k_it
         significance of some values (in the branch instruction, for
         example).  */
       int pcrel_fix;
+#ifdef OBJ_ELF
+      /* Whether this expression needs special pic relocation, and if
+        so, which.  */
+      enum pic_relocation pic_reloc;
+#endif
     }
   reloc[5];                    /* Five is enough??? */
 };
@@ -252,6 +260,9 @@ add_fix (width, exp, pc_rel, pc_fix)
   the_ins.reloc[the_ins.nrel].exp = exp->exp;
   the_ins.reloc[the_ins.nrel].wid = width;
   the_ins.reloc[the_ins.nrel].pcrel_fix = pc_fix;
+#ifdef OBJ_ELF
+  the_ins.reloc[the_ins.nrel].pic_reloc = exp->pic_reloc;
+#endif
   the_ins.reloc[the_ins.nrel++].pcrel = pc_rel;
 }
 
@@ -315,36 +326,37 @@ static int current_architecture;
 struct m68k_cpu {
   unsigned long arch;
   const char *name;
+  int alias;
 };
 
 static const struct m68k_cpu archs[] = {
-  { m68000, "68000" },
-  { m68010, "68010" },
-  { m68020, "68020" },
-  { m68030, "68030" },
-  { m68040, "68040" },
-  { m68060, "68060" },
-  { cpu32,  "cpu32" },
-  { m68881, "68881" },
-  { m68851, "68851" },
+  { m68000, "68000", 0 },
+  { m68010, "68010", 0 },
+  { m68020, "68020", 0 },
+  { m68030, "68030", 0 },
+  { m68040, "68040", 0 },
+  { m68060, "68060", 0 },
+  { cpu32,  "cpu32", 0 },
+  { m68881, "68881", 0 },
+  { m68851, "68851", 0 },
   /* Aliases (effectively, so far as gas is concerned) for the above
      cpus.  */
-  { m68020, "68k" },
-  { m68000, "68302" },
-  { m68000, "68008" },
-  { m68000, "68ec000" },
-  { m68000, "68hc000" },
-  { m68000, "68hc001" },
-  { m68020, "68ec020" },
-  { m68030, "68ec030" },
-  { m68040, "68ec040" },
-  { cpu32,  "68330" },
-  { cpu32,  "68331" },
-  { cpu32,  "68332" },
-  { cpu32,  "68333" },
-  { cpu32,  "68340" },
-  { cpu32,  "68360" },
-  { m68881, "68882" },
+  { m68020, "68k", 1 },
+  { m68000, "68302", 1 },
+  { m68000, "68008", 1 },
+  { m68000, "68ec000", 1 },
+  { m68000, "68hc000", 1 },
+  { m68000, "68hc001", 1 },
+  { m68020, "68ec020", 1 },
+  { m68030, "68ec030", 1 },
+  { m68040, "68ec040", 1 },
+  { cpu32,  "68330", 1 },
+  { cpu32,  "68331", 1 },
+  { cpu32,  "68332", 1 },
+  { cpu32,  "68333", 1 },
+  { cpu32,  "68340", 1 },
+  { cpu32,  "68360", 1 },
+  { m68881, "68882", 1 },
 };
 
 static const int n_archs = sizeof (archs) / sizeof (archs[0]);
@@ -419,7 +431,7 @@ relax_typeS md_relax_table[] =
    function to call to execute this pseudo-op
    Integer arg to pass to the function
    */
-CONST pseudo_typeS md_pseudo_table[] =
+const pseudo_typeS md_pseudo_table[] =
 {
   {"data1", s_data1, 0},
   {"data2", s_data2, 0},
@@ -427,12 +439,14 @@ CONST pseudo_typeS md_pseudo_table[] =
   {"even", s_even, 0},
   {"skip", s_space, 0},
   {"proc", s_proc, 0},
-#ifdef TE_SUN3
+#if defined (TE_SUN3) || defined (OBJ_ELF)
   {"align", s_align_bytes, 0},
 #endif
 #ifdef OBJ_ELF
   {"swbeg", s_ignore, 0},
 #endif
+  {"extend", float_cons, 'x'},
+  {"ldouble", float_cons, 'x'},
 
   /* The following pseudo-ops are supported for MRI compatibility.  */
   {"chip", s_chip, 0},
@@ -497,7 +511,11 @@ CONST pseudo_typeS mote_pseudo_table[] =
   {"dsb", s_space, 1},
 
   {"xdef", s_globl, 0},
+#ifdef OBJ_ELF
+  {"align", s_align_bytes, 0},
+#else
   {"align", s_align_ptwo, 0},
+#endif
 #ifdef M68KCOFF
   {"sect", obj_coff_section, 0},
   {"section", obj_coff_section, 0},
@@ -511,7 +529,7 @@ CONST pseudo_typeS mote_pseudo_table[] =
 #define isuword(x)     ((x)>=0 && (x)<=65535)
 
 #define isbyte(x)      ((x)>= -255 && (x)<=255)
-#define isword(x)      ((x)>=-32768 && (x)<=65535)
+#define isword(x)      ((x)>=-65536 && (x)<=65535)
 #define islong(x)      (1)
 
 extern char *input_line_pointer;
@@ -562,6 +580,8 @@ short
 tc_coff_fix2rtype (fixP)
      fixS *fixP;
 {
+  if (fixP->fx_tcbit && fixP->fx_size == 4)
+    return R_RELLONG_NEG;
 #ifdef NO_PCREL_RELOCS
   know (fixP->fx_pcrel == 0);
   return (fixP->fx_size == 1 ? R_RELBYTE
@@ -580,6 +600,145 @@ tc_coff_fix2rtype (fixP)
 
 #endif
 
+#ifdef OBJ_ELF
+
+/* Compute the relocation code for a fixup of SIZE bytes, using pc
+   relative relocation if PCREL is non-zero.  PIC says whether a special
+   pic relocation was requested.  */
+
+static bfd_reloc_code_real_type get_reloc_code
+  PARAMS ((int, int, enum pic_relocation));
+
+static bfd_reloc_code_real_type
+get_reloc_code (size, pcrel, pic)
+     int size;
+     int pcrel;
+     enum pic_relocation pic;
+{
+  switch (pic)
+    {
+    case pic_got_pcrel:
+      switch (size)
+       {
+       case 1:
+         return BFD_RELOC_8_GOT_PCREL;
+       case 2:
+         return BFD_RELOC_16_GOT_PCREL;
+       case 4:
+         return BFD_RELOC_32_GOT_PCREL;
+       }
+      break;
+
+    case pic_got_off:
+      switch (size)
+       {
+       case 1:
+         return BFD_RELOC_8_GOTOFF;
+       case 2:
+         return BFD_RELOC_16_GOTOFF;
+       case 4:
+         return BFD_RELOC_32_GOTOFF;
+       }
+      break;
+
+    case pic_plt_pcrel:
+      switch (size)
+       {
+       case 1:
+         return BFD_RELOC_8_PLT_PCREL;
+       case 2:
+         return BFD_RELOC_16_PLT_PCREL;
+       case 4:
+         return BFD_RELOC_32_PLT_PCREL;
+       }
+      break;
+
+    case pic_plt_off:
+      switch (size)
+       {
+       case 1:
+         return BFD_RELOC_8_PLTOFF;
+       case 2:
+         return BFD_RELOC_16_PLTOFF;
+       case 4:
+         return BFD_RELOC_32_PLTOFF;
+       }
+      break;
+
+    case pic_none:
+      if (pcrel)
+       {
+         switch (size)
+           {
+           case 1:
+             return BFD_RELOC_8_PCREL;
+           case 2:
+             return BFD_RELOC_16_PCREL;
+           case 4:
+             return BFD_RELOC_32_PCREL;
+           }
+       }
+      else
+       {
+         switch (size)
+           {
+           case 1:
+             return BFD_RELOC_8;
+           case 2:
+             return BFD_RELOC_16;
+           case 4:
+             return BFD_RELOC_32;
+           }
+       }
+    }
+
+  as_bad ("Can not do %d byte %s%srelocation", size,
+         pcrel ? "pc-relative " : "",
+         pic == pic_none ? "" : "pic ");
+  return BFD_RELOC_NONE;
+}
+
+/* Here we decide which fixups can be adjusted to make them relative
+   to the beginning of the section instead of the symbol.  Basically
+   we need to make sure that the dynamic relocations are done
+   correctly, so in some cases we force the original symbol to be
+   used.  */
+int
+tc_m68k_fix_adjustable (fixP)
+     fixS *fixP;
+{
+  /* Prevent all adjustments to global symbols. */
+  if (S_IS_EXTERNAL (fixP->fx_addsy))
+    return 0;
+
+  /* adjust_reloc_syms doesn't know about the GOT */
+  switch (fixP->fx_r_type)
+    {
+    case BFD_RELOC_8_GOT_PCREL:
+    case BFD_RELOC_16_GOT_PCREL:
+    case BFD_RELOC_32_GOT_PCREL:
+    case BFD_RELOC_8_GOTOFF:
+    case BFD_RELOC_16_GOTOFF:
+    case BFD_RELOC_32_GOTOFF:
+    case BFD_RELOC_8_PLT_PCREL:
+    case BFD_RELOC_16_PLT_PCREL:
+    case BFD_RELOC_32_PLT_PCREL:
+    case BFD_RELOC_8_PLTOFF:
+    case BFD_RELOC_16_PLTOFF:
+    case BFD_RELOC_32_PLTOFF:
+      return 0;
+
+    default:
+      return 1;
+    }
+}
+
+#else /* !OBJ_ELF */
+
+#define get_reloc_code(SIZE,PCREL,OTHER) NO_RELOC
+
+#endif /* OBJ_ELF */
+
 #ifdef BFD_ASSEMBLER
 
 arelent *
@@ -590,28 +749,53 @@ tc_gen_reloc (section, fixp)
   arelent *reloc;
   bfd_reloc_code_real_type code;
 
-#define F(SZ,PCREL)            (((SZ) << 1) + (PCREL))
-  switch (F (fixp->fx_size, fixp->fx_pcrel))
+  if (fixp->fx_tcbit)
+    abort ();
+
+  if (fixp->fx_r_type != BFD_RELOC_NONE)
+    code = fixp->fx_r_type;
+  else
     {
+#define F(SZ,PCREL)            (((SZ) << 1) + (PCREL))
+      switch (F (fixp->fx_size, fixp->fx_pcrel))
+       {
 #define MAP(SZ,PCREL,TYPE)     case F(SZ,PCREL): code = (TYPE); break
-      MAP (1, 0, BFD_RELOC_8);
-      MAP (2, 0, BFD_RELOC_16);
-      MAP (4, 0, BFD_RELOC_32);
-      MAP (1, 1, BFD_RELOC_8_PCREL);
-      MAP (2, 1, BFD_RELOC_16_PCREL);
-      MAP (4, 1, BFD_RELOC_32_PCREL);
-    default:
-      abort ();
+         MAP (1, 0, BFD_RELOC_8);
+         MAP (2, 0, BFD_RELOC_16);
+         MAP (4, 0, BFD_RELOC_32);
+         MAP (1, 1, BFD_RELOC_8_PCREL);
+         MAP (2, 1, BFD_RELOC_16_PCREL);
+         MAP (4, 1, BFD_RELOC_32_PCREL);
+       default:
+         abort ();
+       }
     }
+#undef F
+#undef MAP
 
   reloc = (arelent *) bfd_alloc_by_size_t (stdoutput, sizeof (arelent));
   assert (reloc != 0);
   reloc->sym_ptr_ptr = &fixp->fx_addsy->bsym;
   reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
+#ifndef OBJ_ELF
   if (fixp->fx_pcrel)
     reloc->addend = fixp->fx_addnumber;
   else
     reloc->addend = 0;
+#else
+  if (!fixp->fx_pcrel)
+    reloc->addend = fixp->fx_addnumber;
+  else if ((fixp->fx_addsy->bsym->flags & BSF_SECTION_SYM) != 0)
+    reloc->addend = (section->vma
+                    + (fixp->fx_pcrel_adjust == 64
+                       ? -1 : fixp->fx_pcrel_adjust)
+                    + fixp->fx_addnumber
+                    + md_pcrel_from (fixp));
+  else
+    reloc->addend = (fixp->fx_offset
+                    + (fixp->fx_pcrel_adjust == 64
+                       ? -1 : fixp->fx_pcrel_adjust));
+#endif
 
   reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
   assert (reloc->howto != 0);
@@ -830,6 +1014,11 @@ m68k_ip (instring)
                           && (opP->disp.exp.X_op != O_constant
                               || ! isword (opP->disp.exp.X_add_number)))
                    losing++;
+                 else if (s[1] == 'W'
+                          && ! isvar (&opP->disp)
+                          && (opP->disp.exp.X_op != O_constant
+                              || ! issword (opP->disp.exp.X_add_number)))
+                   losing++;
                  break;
 
                case '^':
@@ -854,8 +1043,8 @@ m68k_ip (instring)
                  if (opP->mode == CONTROL
                      || opP->mode == FPREG
                      || opP->mode == REGLST
+                     || opP->mode == IMMED
                      || (opP->mode != ABSL
-                         && opP->mode != IMMED
                          && (opP->reg == PC
                              || opP->reg == ZPC)))
                    losing++;
@@ -1222,6 +1411,12 @@ m68k_ip (instring)
                      || opP->mode == AREG
                      || opP->mode == REGLST)
                    losing++;
+                 /* We should accept immediate operands, but they
+                     supposedly have to be quad word, and we don't
+                     handle that.  I would like to see what a Motorola
+                     assembler does before doing something here.  */
+                 if (opP->mode == IMMED)
+                   losing++;
                  break;
 
                case 'f':
@@ -1230,13 +1425,21 @@ m68k_ip (instring)
                    losing++;
                  break;
 
-               case 'P':
+               case '0':
+                 if (opP->mode != CONTROL || opP->reg != TC)
+                   losing++;
+                 break;
+
+               case '1':
+                 if (opP->mode != CONTROL || opP->reg != AC)
+                   losing++;
+                 break;
+
+               case '2':
                  if (opP->mode != CONTROL
-                     || (opP->reg != TC
-                         && opP->reg != CAL
+                     || (opP->reg != CAL
                          && opP->reg != VAL
-                         && opP->reg != SCC
-                         && opP->reg != AC))
+                         && opP->reg != SCC))
                    losing++;
                  break;
 
@@ -1336,7 +1539,8 @@ m68k_ip (instring)
                    for (idx = 0; idx < sizeof (archs) / sizeof (archs[0]);
                         idx++)
                      {
-                       if (archs[idx].arch & ok_arch)
+                       if ((archs[idx].arch & ok_arch)
+                           && ! archs[idx].alias)
                          {
                            if (got_one)
                              {
@@ -1416,6 +1620,12 @@ m68k_ip (instring)
                  addword (nextword);
                  baseo = 0;
                  break;
+               case 'W':
+                 if (!issword (nextword))
+                   opP->error = "operand out of range";
+                 addword (nextword);
+                 baseo = 0;
+                 break;
                case 'l':
                  addword (nextword >> 16);
                  addword (nextword);
@@ -1533,6 +1743,9 @@ m68k_ip (instring)
                           && cpu_of_arch (current_architecture) >= m68020)
                          || opP->disp.size == SIZE_LONG)))
                {
+                 if (cpu_of_arch (current_architecture) < m68020)
+                   opP->error =
+                     "displacement too large for this architecture; needs 68020 or higher";
                  if (opP->reg == PC)
                    tmpreg = 0x3B;      /* 7.3 */
                  else
@@ -1541,16 +1754,24 @@ m68k_ip (instring)
                    {
                      if (opP->reg == PC)
                        {
-#if 0
-                         addword (0x0170);
-                         add_fix ('l', &opP->disp, 1, 2);
-                         addword (0), addword (0);
-#else
-                         add_frag (adds (&opP->disp),
-                                   offs (&opP->disp),
-                                   TAB (PCLEA, SZ_UNDEF));
+                         if (opP->disp.size == SIZE_LONG
+#ifdef OBJ_ELF
+                             /* If the displacement needs pic
+                                relocation it cannot be relaxed.  */
+                             || opP->disp.pic_reloc != pic_none
 #endif
-                         break;
+                             )
+                           {
+                             addword (0x0170);
+                             add_fix ('l', &opP->disp, 1, 2);
+                           }
+                         else
+                           {
+                             add_frag (adds (&opP->disp),
+                                       offs (&opP->disp),
+                                       TAB (PCLEA, SZ_UNDEF));
+                             break;
+                           }
                        }
                      else
                        {
@@ -1696,7 +1917,13 @@ m68k_ip (instring)
                      else if (siz1 == SIZE_UNSPEC
                               && opP->reg == PC
                               && isvar (&opP->disp)
-                              && subs (&opP->disp) == NULL)
+                              && subs (&opP->disp) == NULL
+#ifdef OBJ_ELF
+                              /* If the displacement needs pic
+                                 relocation it cannot be relaxed.  */
+                              && opP->disp.pic_reloc == pic_none
+#endif
+                              )
                        {
                          nextword += baseo & 0xff;
                          addword (nextword);
@@ -1832,6 +2059,11 @@ m68k_ip (instring)
                  if (isvar (&opP->disp)
                      && !subs (&opP->disp)
                      && adds (&opP->disp)
+#ifdef OBJ_ELF
+                     /* If the displacement needs pic relocation it
+                        cannot be relaxed.  */
+                     && opP->disp.pic_reloc == pic_none
+#endif
                      && S_GET_SEGMENT (adds (&opP->disp)) == now_seg
                      && cpu_of_arch (current_architecture) >= m68020
                      && !flag_long_jumps
@@ -1901,7 +2133,8 @@ m68k_ip (instring)
                opP->error = "out of range";
              insop (tmpreg, opcode);
              if (isvar (&opP->disp))
-               the_ins.reloc[the_ins.nrel - 1].n = (opcode->m_codenum) * 2;
+               the_ins.reloc[the_ins.nrel - 1].n =
+                 (opcode->m_codenum) * 2 + 1;
              break;
            case 'w':
              if (!isword (tmpreg))
@@ -1910,6 +2143,13 @@ m68k_ip (instring)
              if (isvar (&opP->disp))
                the_ins.reloc[the_ins.nrel - 1].n = (opcode->m_codenum) * 2;
              break;
+           case 'W':
+             if (!issword (tmpreg))
+               opP->error = "out of range";
+             insop (tmpreg, opcode);
+             if (isvar (&opP->disp))
+               the_ins.reloc[the_ins.nrel - 1].n = (opcode->m_codenum) * 2;
+             break;
            case 'l':
              /* Because of the way insop works, we put these two out
                 backwards.  */
@@ -1964,6 +2204,13 @@ m68k_ip (instring)
              if (subs (&opP->disp))    /* We can't relax it */
                goto long_branch;
 
+#ifdef OBJ_ELF
+             /* If the displacement needs pic relocation it cannot be
+                relaxed.  */
+             if (opP->disp.pic_reloc != pic_none)
+               goto long_branch;
+#endif
+
              /* This could either be a symbol, or an absolute
                 address.  No matter, the frag hacking will finger it
                 out.  Not quite: it can't switch from BRANCH to
@@ -2253,7 +2500,9 @@ m68k_ip (instring)
          install_operand (s[1], tmpreg);
          break;
 
-       case 'P':
+       case '0':
+       case '1':
+       case '2':
          switch (opP->reg)
            {
            case TC:
@@ -2489,6 +2738,7 @@ install_operand (mode, val)
       break;
     case 'b':
     case 'w':
+    case 'W':
     case 'l':
       break;
     case 'e':
@@ -2894,7 +3144,8 @@ md_assemble (str)
                              n,
                              &the_ins.reloc[m].exp,
                              the_ins.reloc[m].pcrel,
-                             NO_RELOC);
+                             get_reloc_code (n, the_ins.reloc[m].pcrel,
+                                             the_ins.reloc[m].pic_reloc));
          fixP->fx_pcrel_adjust = the_ins.reloc[m].pcrel_fix;
        }
       return;
@@ -2938,7 +3189,8 @@ md_assemble (str)
                              wid,
                              &the_ins.reloc[m].exp,
                              the_ins.reloc[m].pcrel,
-                             NO_RELOC);
+                             get_reloc_code (wid, the_ins.reloc[m].pcrel,
+                                             the_ins.reloc[m].pic_reloc));
          fixP->fx_pcrel_adjust = the_ins.reloc[m].pcrel_fix;
        }
       (void) frag_var (rs_machine_dependent, 10, 0,
@@ -2974,7 +3226,8 @@ md_assemble (str)
                          wid,
                          &the_ins.reloc[m].exp,
                          the_ins.reloc[m].pcrel,
-                         NO_RELOC);
+                         get_reloc_code (wid, the_ins.reloc[m].pcrel,
+                                         the_ins.reloc[m].pic_reloc));
       fixP->fx_pcrel_adjust = the_ins.reloc[m].pcrel_fix;
     }
 }
@@ -3141,6 +3394,12 @@ md_begin ()
 #endif
 
   init_regtable ();
+
+#ifdef OBJ_ELF
+  record_alignment (text_section, 2);
+  record_alignment (data_section, 2);
+  record_alignment (bss_section, 2);
+#endif
 }
 
 void
@@ -3236,6 +3495,43 @@ m68k_init_after_args ()
     md_relax_table[TAB (PCINDEX, BYTE)].rlx_more = 0;
 }
 
+/* This is called if we go in or out of MRI mode because of the .mri
+   pseudo-op.  */
+
+void
+m68k_mri_mode_change (on)
+     int on;
+{
+  if (on)
+    {
+      if (! flag_reg_prefix_optional)
+       {
+         flag_reg_prefix_optional = 1;
+#ifdef REGISTER_PREFIX
+         init_regtable ();
+#endif
+       }
+      m68k_abspcadd = 1;
+      m68k_rel32 = 0;
+    }
+  else
+    {
+      if (! reg_prefix_optional_seen)
+       {
+#ifdef REGISTER_PREFIX_OPTIONAL
+         flag_reg_prefix_optional = REGISTER_PREFIX_OPTIONAL;
+#else
+         flag_reg_prefix_optional = 0;
+#endif
+#ifdef REGISTER_PREFIX
+         init_regtable ();
+#endif
+       }
+      m68k_abspcadd = 0;
+      m68k_rel32 = 1;
+    }
+}
+
 /* Equal to MAX_PRECISION in atof-ieee.c */
 #define MAX_LITTLENUMS 6
 
@@ -3327,6 +3623,15 @@ md_apply_fix_2 (fixP, val)
   else
     val &= 0x7fffffff;
 
+#ifdef OBJ_ELF
+  if (fixP->fx_addsy)
+    {
+      memset (buf, 0, fixP->fx_size);
+      fixP->fx_addnumber = val;        /* Remember value for emit_reloc */
+      return;
+    }
+#endif
+
   switch (fixP->fx_size)
     {
       /* The cast to offsetT below are necessary to make code correct for
@@ -3354,6 +3659,14 @@ md_apply_fix_2 (fixP, val)
       BAD_CASE (fixP->fx_size);
     }
 
+  /* Fix up a negative reloc.  */
+  if (fixP->fx_addsy == NULL && fixP->fx_subsy != NULL)
+    {
+      fixP->fx_addsy = fixP->fx_subsy;
+      fixP->fx_subsy = NULL;
+      fixP->fx_tcbit = 1;
+    }
+
   /* For non-pc-relative values, it's conceivable we might get something
      like "0xff" for a byte field.  So extend the upper part of the range
      to accept such numbers.  We arbitrarily disallow "-0xff" or "0xff+0xff",
@@ -3849,13 +4162,27 @@ md_estimate_size_before_relax (fragP, segment)
     {
     case TAB (BCC68000, BYTE):
     case TAB (ABRANCH, BYTE):
-      /* We can't do a short jump to the next instruction,
-          so we force word mode.  */
-      if (fragP->fr_symbol && S_GET_VALUE (fragP->fr_symbol) == 0 &&
-         fragP->fr_symbol->sy_frag == fragP->fr_next)
+      /* We can't do a short jump to the next instruction, so in that
+        case we force word mode.  At this point S_GET_VALUE should
+        return the offset of the symbol within its frag.  If the
+        symbol is at the start of a frag, and it is the next frag
+        with any data in it (usually this is just the next frag, but
+        assembler listings may introduce empty frags), we must use
+        word mode.  */
+      if (fragP->fr_symbol && S_GET_VALUE (fragP->fr_symbol) == 0)
        {
-         fragP->fr_subtype = TAB (TABTYPE (fragP->fr_subtype), SHORT);
-         fragP->fr_var += 2;
+         fragS *l;
+
+         for (l = fragP->fr_next;
+              l != fragP->fr_symbol->sy_frag;
+              l = l->fr_next)
+           if (l->fr_fix + l->fr_var != 0)
+             break;
+         if (l == fragP->fr_symbol->sy_frag)
+           {
+             fragP->fr_subtype = TAB (TABTYPE (fragP->fr_subtype), SHORT);
+             fragP->fr_var += 2;
+           }
        }
       break;
     default:
@@ -4219,7 +4546,14 @@ static void
 s_chip (ignore)
      int ignore;
 {
+  char *stop = NULL;
+  char stopc;
+
+  if (flag_mri)
+    stop = mri_comment_field (&stopc);
   mri_chip ();
+  if (flag_mri)
+    mri_comment_end (stop, stopc);
   demand_empty_rest_of_line ();
 }
 
@@ -4480,6 +4814,8 @@ s_reg (ignore)
   int c;
   struct m68k_op rop;
   unsigned long mask;
+  char *stop = NULL;
+  char stopc;
 
   if (line_label == NULL)
     {
@@ -4488,6 +4824,9 @@ s_reg (ignore)
       return;
     }
 
+  if (flag_mri)
+    stop = mri_comment_field (&stopc);
+
   SKIP_WHITESPACE ();
 
   s = input_line_pointer;
@@ -4542,6 +4881,9 @@ s_reg (ignore)
   S_SET_VALUE (line_label, mask);
   line_label->sy_frag = &zero_address_frag;
 
+  if (flag_mri)
+    mri_comment_end (stop, stopc);
+
   demand_empty_rest_of_line ();
 }
 
@@ -4680,12 +5022,12 @@ static struct mri_control_info *push_mri_control
 static void pop_mri_control PARAMS ((void));
 static int parse_mri_condition PARAMS ((int *));
 static int parse_mri_control_operand
-  PARAMS ((int *, const char **, const char **, const char **, const char **));
+  PARAMS ((int *, char **, char **, char **, char **));
 static int swap_mri_condition PARAMS ((int));
 static int reverse_mri_condition PARAMS ((int));
 static void build_mri_control_operand
-  PARAMS ((int, int, const char *, const char *, const char *, const char *,
-          const char *, const char *, int));
+  PARAMS ((int, int, char *, char *, char *, char *, const char *,
+          const char *, int));
 static void parse_mri_control_expression
   PARAMS ((char *, int, const char *, const char *, int));
 
@@ -4781,10 +5123,10 @@ parse_mri_condition (pcc)
 static int
 parse_mri_control_operand (pcc, leftstart, leftstop, rightstart, rightstop)
      int *pcc;
-     const char **leftstart;
-     const char **leftstop;
-     const char **rightstart;
-     const char **rightstop;
+     char **leftstart;
+     char **leftstop;
+     char **rightstart;
+     char **rightstop;
 {
   char *s;
 
@@ -4908,10 +5250,10 @@ build_mri_control_operand (qual, cc, leftstart, leftstop, rightstart,
                           rightstop, truelab, falselab, extent)
      int qual;
      int cc;
-     const char *leftstart;
-     const char *leftstop;
-     const char *rightstart;
-     const char *rightstop;
+     char *leftstart;
+     char *leftstop;
+     char *rightstart;
+     char *rightstop;
      const char *truelab;
      const char *falselab;
      int extent;
@@ -4919,19 +5261,42 @@ build_mri_control_operand (qual, cc, leftstart, leftstop, rightstart,
   char *buf;
   char *s;
 
-  /* The 68k can't do a general comparision with an immediate operand
-     on the right hand side.  */
-  if (rightstart != NULL && *rightstart == '#')
+  if (leftstart != NULL)
     {
-      const char *temp;
-
-      cc = swap_mri_condition (cc);
-      temp = leftstart;
-      leftstart = rightstart;
-      rightstart = temp;
-      temp = leftstop;
-      leftstop = rightstop;
-      rightstop = temp;
+      struct m68k_op leftop, rightop;
+      char c;
+
+      /* Swap the compare operands, if necessary, to produce a legal
+        m68k compare instruction.  Comparing a register operand with
+        a non-register operand requires the register to be on the
+        right (cmp, cmpa).  Comparing an immediate value with
+        anything requires the immediate value to be on the left
+        (cmpi).  */
+
+      c = *leftstop;
+      *leftstop = '\0';
+      (void) m68k_ip_op (leftstart, &leftop);
+      *leftstop = c;
+
+      c = *rightstop;
+      *rightstop = '\0';
+      (void) m68k_ip_op (rightstart, &rightop);
+      *rightstop = c;
+
+      if (rightop.mode == IMMED
+         || ((leftop.mode == DREG || leftop.mode == AREG)
+             && (rightop.mode != DREG && rightop.mode != AREG)))
+       {
+         char *temp;
+
+         cc = swap_mri_condition (cc);
+         temp = leftstart;
+         leftstart = rightstart;
+         rightstart = temp;
+         temp = leftstop;
+         leftstop = rightstop;
+         rightstop = temp;
+       }
     }
 
   if (truelab == NULL)
@@ -4992,10 +5357,10 @@ parse_mri_control_expression (stop, qual, truelab, falselab, extent)
 {
   int c;
   int cc;
-  const char *leftstart;
-  const char *leftstop;
-  const char *rightstart;
-  const char *rightstop;
+  char *leftstart;
+  char *leftstop;
+  char *rightstart;
+  char *rightstop;
 
   c = *stop;
   *stop = '\0';
@@ -5103,7 +5468,8 @@ s_mri_if (qual)
   /* A structured control directive must end with THEN with an
      optional qualifier.  */
   s = input_line_pointer;
-  while (! is_end_of_line[(unsigned char) *s])
+  while (! is_end_of_line[(unsigned char) *s]
+        && (! flag_mri || *s != '*'))
     ++s;
   --s;
   while (s > input_line_pointer && (*s == ' ' || *s == '\t'))
@@ -5154,6 +5520,12 @@ s_mri_if (qual)
   else
     input_line_pointer = s + 1;
 
+  if (flag_mri)
+    {
+      while (! is_end_of_line[(unsigned char) *input_line_pointer])
+       ++input_line_pointer;
+    }
+
   demand_empty_rest_of_line ();
 }
 
@@ -5210,6 +5582,12 @@ s_mri_else (qual)
 
   colon (mri_control_stack->next);
 
+  if (flag_mri)
+    {
+      while (! is_end_of_line[(unsigned char) *input_line_pointer])
+       ++input_line_pointer;
+    }
+
   demand_empty_rest_of_line ();
 }
 
@@ -5236,6 +5614,12 @@ s_mri_endi (ignore)
 
   pop_mri_control ();
 
+  if (flag_mri)
+    {
+      while (! is_end_of_line[(unsigned char) *input_line_pointer])
+       ++input_line_pointer;
+    }
+
   demand_empty_rest_of_line ();
 }
 
@@ -5269,6 +5653,12 @@ s_mri_break (extent)
   md_assemble (buf);
   free (buf);
 
+  if (flag_mri)
+    {
+      while (! is_end_of_line[(unsigned char) *input_line_pointer])
+       ++input_line_pointer;
+    }
+
   demand_empty_rest_of_line ();
 }
 
@@ -5302,6 +5692,12 @@ s_mri_next (extent)
   md_assemble (buf);
   free (buf);
 
+  if (flag_mri)
+    {
+      while (! is_end_of_line[(unsigned char) *input_line_pointer])
+       ++input_line_pointer;
+    }
+
   demand_empty_rest_of_line ();
 }
 
@@ -5529,6 +5925,12 @@ s_mri_for (qual)
   *s = '\0';
   n->incr = buf;
 
+  if (flag_mri)
+    {
+      while (! is_end_of_line[(unsigned char) *input_line_pointer])
+       ++input_line_pointer;
+    }
+
   demand_empty_rest_of_line ();
 }
 
@@ -5559,6 +5961,12 @@ s_mri_endf (ignore)
 
   pop_mri_control ();
 
+  if (flag_mri)
+    {
+      while (! is_end_of_line[(unsigned char) *input_line_pointer])
+       ++input_line_pointer;
+    }
+
   demand_empty_rest_of_line ();
 }
 
@@ -5572,6 +5980,11 @@ s_mri_repeat (ignore)
 
   n = push_mri_control (mri_repeat);
   colon (n->top);
+  if (flag_mri)
+    {
+      while (! is_end_of_line[(unsigned char) *input_line_pointer])
+       ++input_line_pointer;
+    }
   demand_empty_rest_of_line ();
 }
 
@@ -5603,6 +6016,14 @@ s_mri_until (qual)
 
   input_line_pointer = s;
 
+  pop_mri_control ();
+
+  if (flag_mri)
+    {
+      while (! is_end_of_line[(unsigned char) *input_line_pointer])
+       ++input_line_pointer;
+    }
+
   demand_empty_rest_of_line ();
 }
 
@@ -5617,7 +6038,8 @@ s_mri_while (qual)
   struct mri_control_info *n;
 
   s = input_line_pointer;
-  while (! is_end_of_line[(unsigned char) *s])
+  while (! is_end_of_line[(unsigned char) *s]
+        && (! flag_mri || *s != '*'))
     s++;
   --s;
   while (*s == ' ' || *s == '\t')
@@ -5644,6 +6066,12 @@ s_mri_while (qual)
   if (*input_line_pointer == '.')
     input_line_pointer += 2;
 
+  if (flag_mri)
+    {
+      while (! is_end_of_line[(unsigned char) *input_line_pointer])
+       ++input_line_pointer;
+    }
+
   demand_empty_rest_of_line ();
 }
 
@@ -5672,6 +6100,12 @@ s_mri_endw (ignore)
 
   pop_mri_control ();
 
+  if (flag_mri)
+    {
+      while (! is_end_of_line[(unsigned char) *input_line_pointer])
+       ++input_line_pointer;
+    }
+
   demand_empty_rest_of_line ();
 }
 \f
@@ -5813,10 +6247,17 @@ md_parse_option (c, arg)
 
     case OPTION_REGISTER_PREFIX_OPTIONAL:
       flag_reg_prefix_optional = 1;
+      reg_prefix_optional_seen = 1;
       break;
 
-    case 'Q':
+      /* -V: SVR4 argument to print version ID.  */
     case 'V':
+      print_version_id ();
+      break;
+
+      /* -Qy, -Qn: SVR4 arguments controlling whether a .comment section
+        should be emitted or not.  FIXME: Not implemented.  */
+    case 'Q':
       break;
 
     default:
This page took 0.038721 seconds and 4 git commands to generate.