gas/
[deliverable/binutils-gdb.git] / gas / config / tc-d10v.c
index 6b534095ef513c4b67fb4fc4d291de6014ea3bf8..23bf1bbb9472c9552274f4363936fb406772cae5 100644 (file)
@@ -1,5 +1,5 @@
 /* tc-d10v.c -- Assembler code for the Mitsubishi D10V
-   Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002
+   Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
    Free Software Foundation, Inc.
 
    This file is part of GAS, the GNU Assembler.
@@ -71,13 +71,13 @@ typedef int packing_type;
 #define PACK_RIGHT_LEFT (3)    /* "<-"  */
 static packing_type etype = PACK_UNSPEC; /* Used by d10v_cleanup.  */
 
-/* True if instruction swapping warnings should be inhibited.
+/* TRUE if instruction swapping warnings should be inhibited.
    --nowarnswap.  */
-static boolean flag_warn_suppress_instructionswap;
+static bfd_boolean flag_warn_suppress_instructionswap;
 
-/* True if instruction packing should be performed when --gstabs is specified.
+/* TRUE if instruction packing should be performed when --gstabs is specified.
    --gstabs-packing, --no-gstabs-packing.  */
-static boolean flag_allow_gstabs_packing = 1;
+static bfd_boolean flag_allow_gstabs_packing = 1;
 
 /* Local functions.  */
 static int reg_name_search PARAMS ((char *name));
@@ -647,8 +647,15 @@ build_insn (opcode, opers, insn)
              opers[i].X_add_number = number;
            }
          else
-           fixups->fix[fixups->fc].reloc =
-             get_reloc ((struct d10v_operand *) &d10v_operands[opcode->operands[i]]);
+           {
+             fixups->fix[fixups->fc].reloc =
+               get_reloc ((struct d10v_operand *) &d10v_operands[opcode->operands[i]]);
+
+             /* Check that an immediate was passed to ops that expect one.  */
+             if ((flags & OPERAND_NUM)
+                 && (fixups->fix[fixups->fc].reloc == 0))
+               as_bad (_("operand is not an immediate"));
+           }
 
          if (fixups->fix[fixups->fc].reloc == BFD_RELOC_16 ||
              fixups->fix[fixups->fc].reloc == BFD_RELOC_D10V_18)
@@ -659,7 +666,7 @@ build_insn (opcode, opers, insn)
          fixups->fix[fixups->fc].exp = opers[i];
          fixups->fix[fixups->fc].operand = opcode->operands[i];
          fixups->fix[fixups->fc].pcrel =
-           (flags & OPERAND_ADDR) ? true : false;
+           (flags & OPERAND_ADDR) ? TRUE : FALSE;
          (fixups->fc)++;
        }
 
@@ -941,11 +948,10 @@ parallel_ok (op1, insn1, op2, insn2, exec_type)
       || (op1->unit == MU && op2->unit == MU))
     return 0;
 
-  /* If this is auto parallization, and either instruction is a branch,
-     don't parallel.  */
+  /* If this is auto parallelization, and the first instruction is a
+     branch or should not be packed, then don't parallelize.  */
   if (exec_type == PACK_UNSPEC
-      && (op1->exec_type & (ALONE | BRANCH)
-         || op2->exec_type & (ALONE | BRANCH)))
+      && (op1->exec_type & (ALONE | BRANCH)))
     return 0;
 
   /* The idea here is to create two sets of bitmasks (mod and used)
@@ -1057,7 +1063,7 @@ check_resource_conflict (op1, insn1, op2, insn2)
      unsigned long insn1, insn2;
 {
   int i, j, flags, mask, shift, regno;
-  unsigned long ins, mod[2], used[2];
+  unsigned long ins, mod[2];
   struct d10v_opcode *op;
 
   if ((op1->exec_type & SEQ)
@@ -1076,20 +1082,17 @@ check_resource_conflict (op1, insn1, op2, insn2)
       return;
     }
 
-  /* The idea here is to create two sets of bitmasks (mod and used)
-     which indicate which registers are modified or used by each
-     instruction.  The operation can only be done in parallel if
-     instruction 1 and instruction 2 modify different registers, and
-     the first instruction does not modify registers that the second
-     is using (The second instruction can modify registers that the
-     first is using as they are only written back after the first
-     instruction has completed).  Accesses to control registers
-     and memory are treated as accesses to a single register.  So if
-     both instructions write memory or if the first instruction writes
-     memory and the second reads, then they cannot be done in
-     parallel. We treat reads to the PSW (which includes C, F0, and F1)
-     in isolation. So simultaneously writing C and F0 in two different
-     sub-instructions is permitted.  */
+   /* See if both instructions write to the same resource.
+
+      The idea here is to create two sets of bitmasks (mod and used) which
+      indicate which registers are modified or used by each instruction.
+      The operation can only be done in parallel if neither instruction
+      modifies the same register. Accesses to control registers and memory
+      are treated as accesses to a single register. So if both instructions
+      write memory or if the first instruction writes memory and the second
+      reads, then they cannot be done in parallel. We treat reads to the PSW
+      (which includes C, F0, and F1) in isolation. So simultaneously writing
+      C and F0 in two different sub-instructions is permitted.  */
 
   /* The bitmasks (mod and used) look like this (bit 31 = MSB).
      r0-r15      0-15
@@ -1112,7 +1115,7 @@ check_resource_conflict (op1, insn1, op2, insn2)
          op = op2;
          ins = insn2;
        }
-      mod[j] = used[j] = 0;
+      mod[j] = 0;
       if (op->exec_type & BRANCH_LINK)
        mod[j] |= 1 << 13;
 
@@ -1138,43 +1141,32 @@ check_resource_conflict (op1, insn1, op2, insn2)
              else if (flags & OPERAND_CFLAG)
                regno = 21;
 
-             if ( flags & OPERAND_DEST )
+             if (flags & OPERAND_DEST
+                 /* Auto inc/dec also modifies the register.  */
+                 || (op->operands[i + 1] != 0
+                     && (d10v_operands[op->operands[i + 1]].flags
+                         & (OPERAND_PLUS | OPERAND_MINUS)) != 0))
                {
                  mod[j] |= 1 << regno;
                  if (flags & OPERAND_EVEN)
                    mod[j] |= 1 << (regno + 1);
                }
-             else
-               {
-                 used[j] |= 1 << regno ;
-                 if (flags & OPERAND_EVEN)
-                   used[j] |= 1 << (regno + 1);
-
-                 /* Auto inc/dec also modifies the register.  */
-                 if (op->operands[i+1] != 0
-                     && (d10v_operands[op->operands[i+1]].flags
-                         & (OPERAND_PLUS | OPERAND_MINUS)) != 0)
-                   mod[j] |= 1 << regno;
-               }
            }
          else if (flags & OPERAND_ATMINUS)
            {
              /* SP implicitly used/modified.  */
              mod[j] |= 1 << 15;
-             used[j] |= 1 << 15;
            }
        }
-      if (op->exec_type & RMEM)
-       used[j] |= 1 << 20;
-      else if (op->exec_type & WMEM)
+
+      if (op->exec_type & WMEM)
        mod[j] |= 1 << 20;
-      else if (op->exec_type & RF0)
-       used[j] |= 1 << 22;
       else if (op->exec_type & WF0)
        mod[j] |= 1 << 22;
       else if (op->exec_type & WCAR)
        mod[j] |= 1 << 21;
     }
+
   if ((mod[0] & mod[1]) == 0)
     return;
   else
@@ -1198,7 +1190,7 @@ check_resource_conflict (op1, insn1, op2, insn2)
 }
 
 /* This is the main entry point for the machine-dependent assembler.
-   STR points to a machine-dependent instruction.  This function is
+   str points to a machine-dependent instruction.  This function is
    supposed to emit the frags/bytes it assembles to.  For the D10V, it
    mostly handles the special VLIW parsing and packing and leaves the
    difficult stuff to do_assemble().  */
@@ -1462,14 +1454,14 @@ find_opcode (opcode, myops)
                  unsigned long current_position;
                  unsigned long symbol_position;
                  unsigned long value;
-                 boolean found_symbol;
+                 bfd_boolean found_symbol;
 
                  /* Calculate the address of the current instruction
                     and the address of the symbol.  Do this by summing
                     the offsets of previous frags until we reach the
                     frag containing the symbol, and the current frag.  */
                  sym_frag = symbol_get_frag (myops[opnum].X_add_symbol);
-                 found_symbol = false;
+                 found_symbol = FALSE;
 
                  current_position =
                    obstack_next_free (&frchain_now->frch_obstack)
@@ -1481,7 +1473,7 @@ find_opcode (opcode, myops)
                      current_position += f->fr_fix + f->fr_offset;
 
                      if (f == sym_frag)
-                       found_symbol = true;
+                       found_symbol = TRUE;
 
                      if (! found_symbol)
                        symbol_position += f->fr_fix + f->fr_offset;
@@ -1669,11 +1661,10 @@ tc_gen_reloc (seg, fixp)
       return NULL;
     }
 
-  if (fixp->fx_r_type == BFD_RELOC_VTABLE_INHERIT
-      || fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
+  if (fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
     reloc->address = fixp->fx_offset;
 
-  reloc->addend = fixp->fx_addnumber;
+  reloc->addend = 0;
 
   return reloc;
 }
@@ -1702,37 +1693,21 @@ md_pcrel_from_section (fixp, sec)
 void
 md_apply_fix3 (fixP, valP, seg)
      fixS *fixP;
-     valueT * valP;
+     valueT *valP;
      segT seg ATTRIBUTE_UNUSED;
 {
   char *where;
   unsigned long insn;
-  long value = * (long *) valP;
+  long value = *valP;
   int op_type;
   int left = 0;
 
   if (fixP->fx_addsy == (symbolS *) NULL)
     fixP->fx_done = 1;
 
-  else if (fixP->fx_pcrel)
-    ;
-
-  else
-    {
-      value = fixP->fx_offset;
-
-      if (fixP->fx_subsy != (symbolS *) NULL)
-       {
-         if (S_GET_SEGMENT (fixP->fx_subsy) == absolute_section)
-           value -= S_GET_VALUE (fixP->fx_subsy);
-         else
-           {
-             /* We don't actually support subtracting a symbol.  */
-             as_bad_where (fixP->fx_file, fixP->fx_line,
-                           _("expression too complex"));
-           }
-       }
-    }
+  /* We don't actually support subtracting a symbol.  */
+  if (fixP->fx_subsy != (symbolS *) NULL)
+    as_bad_where (fixP->fx_file, fixP->fx_line, _("expression too complex"));
 
   op_type = fixP->fx_r_type;
   if (op_type & 2048)
@@ -1769,13 +1744,13 @@ md_apply_fix3 (fixP, valP, seg)
          XXX - Do we have to worry about branches to a symbol + offset ?  */
       if (fixP->fx_addsy != NULL
          && S_IS_EXTERN (fixP->fx_addsy) )
-       {
-         segT fseg = S_GET_SEGMENT (fixP->fx_addsy);
-         segment_info_type *segf = seg_info(fseg);
+        {
+          segT fseg = S_GET_SEGMENT (fixP->fx_addsy);
+          segment_info_type *segf = seg_info(fseg);
 
          if ( segf && segf->sym != fixP->fx_addsy)
            value = 0;
-       }
+        }
       /* Drop through.  */
     case BFD_RELOC_D10V_18:
       /* Instruction addresses are always right-shifted by 2.  */
@@ -1917,20 +1892,10 @@ md_operand (expressionP)
     }
 }
 
-boolean
+bfd_boolean
 d10v_fix_adjustable (fixP)
      fixS *fixP;
 {
-  if (fixP->fx_addsy == NULL)
-    return 1;
-
-  /* Prevent all adjustments to global and weak symbols or symbols in
-     merge sections.  */
-  if ((S_IS_EXTERN (fixP->fx_addsy)
-       || (S_IS_WEAK (fixP->fx_addsy))
-       || (S_GET_SEGMENT (fixP->fx_addsy)->flags & SEC_MERGE) != 0))
-    return 0;
-
   /* We need the symbol name for the VTABLE entries.  */
   if (fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
       || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
@@ -1938,14 +1903,3 @@ d10v_fix_adjustable (fixP)
 
   return 1;
 }
-
-int
-d10v_force_relocation (fixp)
-     fixS *fixp;
-{
-  if (fixp->fx_r_type == BFD_RELOC_VTABLE_INHERIT
-      || fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
-    return 1;
-
-  return 0;
-}
This page took 0.028638 seconds and 4 git commands to generate.