* config/tc-arc.c (byte_order): Provide explicit initial value.
authorDavid Edelsohn <dje.gcc@gmail.com>
Fri, 14 Jul 1995 17:31:30 +0000 (17:31 +0000)
committerDavid Edelsohn <dje.gcc@gmail.com>
Fri, 14 Jul 1995 17:31:30 +0000 (17:31 +0000)
gas/config/tc-arc.c

index febab3d..fd14c58 100644 (file)
@@ -16,7 +16,7 @@
 
    You should have received a copy of the GNU General Public License
    along with GAS; see the file COPYING.  If not, write to
-   the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+   the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
 
 #include <stdio.h>
 #include <ctype.h>
@@ -31,7 +31,6 @@ static arc_insn arc_insert_operand PARAMS ((arc_insn,
                                            const struct arc_operand *, int,
                                            const struct arc_operand_value *,
                                            offsetT, char *, unsigned int));
-static int delay_slot_type PARAMS ((arc_insn));
 static void arc_common PARAMS ((int));
 static void arc_cpu PARAMS ((int));
 /*static void arc_rename PARAMS ((int));*/
@@ -77,7 +76,7 @@ const char FLT_CHARS[] = "rRsSfFdD";
 /* Byte order.  */
 extern int target_big_endian;
 const char *arc_target_format = DEFAULT_TARGET_FORMAT;
-static int byte_order;
+static int byte_order = DEFAULT_BYTE_ORDER;
 
 /* One of bfd_mach_arc_xxx.  */
 static int arc_mach_type = bfd_mach_arc_base;
@@ -278,18 +277,6 @@ arc_insert_operand (insn, operand, mods, reg, val, file, line)
   return insn;
 }
 
-/* Return the delay slot type for INSN (or -1 if it isn't a branch).  */
-/* ??? This is a quick hack.  May wish to later generalize this concept
-   to record all suffixes the insn contains (for various warnings, etc.).  */
-
-static int
-delay_slot_type (arc_insn insn)
-{
-  if ((insn >> 27) >= 4 && (insn >> 27) <= 7)
-    return (insn & 0x60) >> 5;
-  return -1;
-}
-
 /* We need to keep a list of fixups.  We can't simply generate them as
    we go, because that would require us to first create the frag, and
    that would screw up references to ``.''.  */
@@ -301,7 +288,9 @@ struct arc_fixup
   expressionS exp;
 };
 
-#define MAX_INSN_FIXUPS 5
+#define MAX_FIXUPS 5
+
+#define MAX_SUFFIXES 5
 
 /* This routine is called for each instruction to be assembled.  */
 
@@ -329,17 +318,20 @@ md_assemble (str)
   /* The instructions are stored in lists hashed by the first letter (though
      we needn't care how they're hashed).  Get the first in the list.  */
 
-  opcode = arc_opcode_asm_list (str);
+  opcode = arc_opcode_lookup_asm (str);
 
   /* Keep looking until we find a match.  */
 
   start = str;
   for ( ; opcode != NULL; opcode = ARC_OPCODE_NEXT_ASM (opcode))
     {
-      int past_opcode_p;
+      int past_opcode_p, fc, num_suffixes;
       char *syn;
-      struct arc_fixup fixups[MAX_INSN_FIXUPS];
-      int fc,limm_reloc_p;
+      struct arc_fixup fixups[MAX_FIXUPS];
+      /* Used as a sanity check.  If we need a limm reloc, make sure we ask
+        for an extra 4 bytes from frag_more.  */
+      int limm_reloc_p;
+      const struct arc_operand_value *insn_suffixes[MAX_SUFFIXES];
 
       /* Is this opcode supported by the selected cpu?  */
       if (! arc_opcode_supported (opcode))
@@ -351,9 +343,7 @@ md_assemble (str)
       insn = opcode->value;
       fc = 0;
       past_opcode_p = 0;
-
-      /* Used as a sanity check.  If we need a limm reloc, make sure we ask
-        for an extra 4 bytes from frag_more.  */
+      num_suffixes = 0;
       limm_reloc_p = 0;
 
       /* We don't check for (*str != '\0') here because we want to parse
@@ -471,7 +461,7 @@ md_assemble (str)
              suffix_end = arc_suffixes + arc_suffixes_count;
              for (suffix = suf;
                   suffix < suffix_end && strcmp (suffix->name, suf->name) == 0;
-                  suffix++)
+                  ++suffix)
                {
                  if (arc_operands[suffix->type].fmt == *syn)
                    {
@@ -490,9 +480,14 @@ md_assemble (str)
                }
              ++syn;
              if (!found)
-               /* There's nothing to do except go on to try the next one.
-                  ??? This test can be deleted when we're done.  */
-               ;
+               ; /* Wrong type.  Just go on to try next insn entry.  */
+             else
+               {
+                 if (num_suffixes == MAX_SUFFIXES)
+                   as_bad ("too many suffixes");
+                 else
+                   insn_suffixes[num_suffixes++] = suffix;
+               }
            }
          else
            /* This is either a register or an expression of some kind.  */
@@ -548,7 +543,7 @@ md_assemble (str)
              else
                {
                  /* We need to generate a fixup for this expression.  */
-                 if (fc >= MAX_INSN_FIXUPS)
+                 if (fc >= MAX_FIXUPS)
                    as_fatal ("too many fixups");
                  fixups[fc].exp = exp;
 
@@ -605,6 +600,7 @@ md_assemble (str)
        }
 
       /* If we're at the end of the syntax string, we're done.  */
+      /* FIXME: try to move this to a separate function.  */
       if (*syn == '\0')
        {
          int i;
@@ -625,18 +621,53 @@ md_assemble (str)
          /* Is there a limm value?  */
          limm_p = arc_opcode_limm_p (&limm);
 
-         /* Putting an insn with a limm value in a delay slot is supposed to
-            be legal, but let's warn the user anyway.  Ditto for 8 byte jumps
-            with delay slots.  */
+         /* Perform various error and warning tests.  */
+
          {
            static int in_delay_slot_p = 0;
-           int this_insn_delay_slot_type = delay_slot_type (insn);
+           static int prev_insn_needs_cc_nop_p = 0;
+           /* delay slot type seen */
+           int delay_slot_type = ARC_DELAY_NONE;
+           /* conditional execution flag seen */
+           int conditional = 0;
+           /* 1 if condition codes are being set */
+           int cc_set_p = 0;
+           /* 1 if conditional branch, including `b' "branch always" */
+           int cond_branch_p = opcode->flags & ARC_OPCODE_COND_BRANCH;
+           int need_cc_nop_p = 0;
+
+           for (i = 0; i < num_suffixes; ++i)
+             {
+               switch (arc_operands[insn_suffixes[i]->type].fmt)
+                 {
+                 case 'n' :
+                   delay_slot_type = insn_suffixes[i]->value;
+                   break;
+                 case 'q' :
+                   conditional = insn_suffixes[i]->value;
+                   break;
+                 case 'f' :
+                   cc_set_p = 1;
+                   break;
+                 }
+             }
 
+           /* Putting an insn with a limm value in a delay slot is supposed to
+              be legal, but let's warn the user anyway.  Ditto for 8 byte
+              jumps with delay slots.  */
            if (in_delay_slot_p && limm_p)
              as_warn ("8 byte instruction in delay slot");
-           if (this_insn_delay_slot_type > 0 && limm_p)
+           if (delay_slot_type != ARC_DELAY_NONE && limm_p)
              as_warn ("8 byte jump instruction with delay slot");
-           in_delay_slot_p = (this_insn_delay_slot_type > 0) && !limm_p;
+           in_delay_slot_p = (delay_slot_type != ARC_DELAY_NONE) && !limm_p;
+
+           /* Warn when a conditional branch immediately follows a set of
+              the condition codes.  Note that this needn't be done if the
+              insn that sets the condition codes uses a limm.  */
+           if (cond_branch_p && conditional != 0 /* 0 = "always" */
+               && prev_insn_needs_cc_nop_p)
+             as_warn ("conditional branch follows set of flags");
+           prev_insn_needs_cc_nop_p = cc_set_p && !limm_p;
          }
 
          /* Write out the instruction.
@@ -1167,8 +1198,10 @@ md_pcrel_from (fixP)
 {
   if (fixP->fx_addsy != (symbolS *) NULL
       && ! S_IS_DEFINED (fixP->fx_addsy))
-    /* Return offset from PC to delay slot.  Offsets are from there.  */
-    return 4;
+    {
+      /* The symbol is undefined.  Let the linker figure it out.  */
+      return 0;
+    }
 
   /* Return the address of the delay slot.  */
   return fixP->fx_frag->fr_address + fixP->fx_where + fixP->fx_size;
@@ -1243,9 +1276,10 @@ get_arc_exp_reloc_type (data_p, default_type, exp, expnew)
    that, we determine the correct reloc code and put it back in the fixup.  */
 
 int
-md_apply_fix (fixP, valueP)
+md_apply_fix3 (fixP, valueP, seg)
      fixS *fixP;
      valueT *valueP;
+     segT seg;
 {
   /*char *buf = fixP->fx_where + fixP->fx_frag->fr_literal;*/
   valueT value;
@@ -1267,7 +1301,16 @@ md_apply_fix (fixP, valueP)
       fixP->fx_done = 1;
     }
   else if (fixP->fx_pcrel)
-    value = *valueP;
+    {
+      value = *valueP;
+      /* ELF relocations are against symbols.
+        If this symbol is in a different section then we need to leave it for
+        the linker to deal with.  Unfortunately, md_pcrel_from can't tell,
+        so we have to undo it's effects here.  */
+      if (S_IS_DEFINED (fixP->fx_addsy)
+         && S_GET_SEGMENT (fixP->fx_addsy) != seg)
+       value += md_pcrel_from (fixP);
+    }
   else
     {
       value = fixP->fx_offset;
@@ -1413,10 +1456,11 @@ tc_gen_reloc (section, fixP)
                    fixP->fx_r_type, bfd_get_reloc_code_name (fixP->fx_r_type));
       return NULL;
     }
-  reloc->addend = fixP->fx_addnumber;
 
   assert (!fixP->fx_pcrel == !reloc->howto->pc_relative);
 
+  reloc->addend = fixP->fx_addnumber;
+
   return reloc;
 }
 \f