include/opcode/
[deliverable/binutils-gdb.git] / gas / config / tc-mep.c
index 6ad68774122e9bc59ce839e7a1f5ef3e6a8a061d..377e4c3f36ed875e0846c9935dbeae72952c54d3 100644 (file)
@@ -1,5 +1,5 @@
 /* tc-mep.c -- Assembler for the Toshiba Media Processor.
-   Copyright (C) 2001, 2002, 2003, 2004, 2005, 2007
+   Copyright (C) 2001, 2002, 2003, 2004, 2005, 2007, 2009, 2012
    Free Software Foundation. Inc.
 
    This file is part of GAS, the GNU Assembler.
@@ -19,8 +19,8 @@
    the Free Software Foundation, 51 Franklin Street, Fifth Floor,
    Boston, MA 02110-1301, USA.  */
 
-#include <stdio.h>
 #include "as.h"
+#include <stdio.h>
 #include "dwarf2dbg.h"
 #include "subsegs.h"
 #include "symcat.h"
@@ -80,8 +80,6 @@ static void mep_noregerr (int);
 const pseudo_typeS md_pseudo_table[] =
 {
   { "word",    cons,                           4 },
-  { "file",    (void (*) (int)) dwarf2_directive_file,         0 },
-  { "loc",     dwarf2_directive_loc,           0 },
   { "vliw",    mep_switch_to_vliw_mode,        0 },
   { "core",    mep_switch_to_core_mode,        0 },
   { "vtext",   mep_s_vtext,                    0 },
@@ -176,6 +174,23 @@ struct option md_longopts[] = {
   { NULL, 0, NULL, 0 } };
 size_t md_longopts_size = sizeof (md_longopts);
 
+/* Options which default to on/off together.  See the comment where
+   this is used for details.  Note that CP and CP64 are not in this
+   list because disabling those overrides the -mivc2 option.  */
+#define OPTION_MASK \
+       ( (1 << CGEN_INSN_OPTIONAL_BIT_INSN) \
+       | (1 << CGEN_INSN_OPTIONAL_MUL_INSN) \
+       | (1 << CGEN_INSN_OPTIONAL_DIV_INSN) \
+       | (1 << CGEN_INSN_OPTIONAL_DEBUG_INSN) \
+       | (1 << CGEN_INSN_OPTIONAL_LDZ_INSN) \
+       | (1 << CGEN_INSN_OPTIONAL_ABS_INSN) \
+       | (1 << CGEN_INSN_OPTIONAL_AVE_INSN) \
+       | (1 << CGEN_INSN_OPTIONAL_MINMAX_INSN) \
+       | (1 << CGEN_INSN_OPTIONAL_CLIP_INSN) \
+       | (1 << CGEN_INSN_OPTIONAL_SAT_INSN) \
+       | (1 << CGEN_INSN_OPTIONAL_UCI_INSN) \
+       | (1 << CGEN_INSN_OPTIONAL_DSP_INSN) )
+
 const char * md_shortopts = "";
 static int optbits = 0;
 static int optbitset = 0;
@@ -392,19 +407,19 @@ mep_check_for_disabled_registers (mep_insn *insn)
        case 7: /* $hi */
        case 8: /* $lo */
          if (!has_mul_div)
-           as_bad ("$hi and $lo are disabled when MUL and DIV are off");
+           as_bad (_("$hi and $lo are disabled when MUL and DIV are off"));
          break;
        case 12: /* $mb0 */
        case 13: /* $me0 */
        case 14: /* $mb1 */
        case 15: /* $me1 */
          if (!has_cop)
-           as_bad ("$mb0, $me0, $mb1, and $me1 are disabled when COP is off");
+           as_bad (_("$mb0, $me0, $mb1, and $me1 are disabled when COP is off"));
          break;
        case 24: /* $dbg */
        case 25: /* $depc */
          if (!has_debug)
-           as_bad ("$dbg and $depc are disabled when DEBUG is off");
+           as_bad (_("$dbg and $depc are disabled when DEBUG is off"));
          break;
        }
     }
@@ -413,7 +428,7 @@ mep_check_for_disabled_registers (mep_insn *insn)
 static int
 mep_machine (void)
 {
-  switch (MEP_CPU)
+  switch (MEP_CPU & EF_MEP_CPU_MASK)
     {
     default: break;
     case EF_MEP_CPU_C2: return bfd_mach_mep;
@@ -462,7 +477,10 @@ md_begin ()
      specified.  If the user specifies options and a config, the
      options modify the config.  */
   if (optbits && mep_config_index == 0)
-    MEP_OMASK = optbits;
+    {
+      MEP_OMASK &= ~OPTION_MASK;
+      MEP_OMASK |= optbits;
+    }
   else
     MEP_OMASK = (MEP_OMASK & ~optbitset) | optbits;
 
@@ -592,10 +610,10 @@ mep_check_parallel32_scheduling (void)
          if (insn0length + insn1length == 32)
            return;
           else
-           as_bad ("core and copro insn lengths must total 32 bits.");
+           as_bad (_("core and copro insn lengths must total 32 bits."));
        }
       else
-        as_bad ("vliw group must consist of 1 core and 1 copro insn."); 
+        as_bad (_("vliw group must consist of 1 core and 1 copro insn.")); 
     }
   else
     {
@@ -729,10 +747,10 @@ mep_check_parallel64_scheduling (void)
          if (insn0length + insn1length == 64)
             return;
          else
-            as_bad ("core and copro insn lengths must total 64 bits.");
+            as_bad (_("core and copro insn lengths must total 64 bits."));
        }
       else
-        as_bad ("vliw group must consist of 1 core and 1 copro insn.");
+        as_bad (_("vliw group must consist of 1 core and 1 copro insn."));
     }
   else
     {
@@ -914,7 +932,7 @@ mep_check_ivc2_scheduling (void)
   */
 
   int slots[5]; /* Indexed off the SLOTS_ATTR enum.  */
-  int corelength;
+  int corelength, realcorelength;
   int i;
   bfd_byte temp[4];
   bfd_byte *f;
@@ -932,10 +950,19 @@ mep_check_ivc2_scheduling (void)
   if (slot_ok (0, SLOTS_CORE))
     {
       slots[SLOTS_CORE] = 0;
-      corelength = CGEN_FIELDS_BITSIZE (& saved_insns[0].fields);
+      realcorelength = corelength = CGEN_FIELDS_BITSIZE (& saved_insns[0].fields);
+
+      /* If we encounter one of these, it may get relaxed later into a
+        longer instruction.  We can't just push the other opcodes
+        away, the bigger insn has to fit into the existing slot.  So,
+        we make room for the relaxed instruction here.  */
+
+      if (saved_insns[0].insn->base->num == MEP_INSN_BSR12
+         || saved_insns[0].insn->base->num == MEP_INSN_BRA)
+       corelength = 32;
     }
   else
-    corelength = 0;
+    realcorelength = corelength = 0;
 
   if (corelength == 16)
     {
@@ -952,7 +979,7 @@ mep_check_ivc2_scheduling (void)
          else if (slot_ok (1, SLOTS_P0S))
            slots[SLOTS_P0S] = 1;
          else
-           as_bad ("cannot pack %s with a 16-bit insn",
+           as_bad (_("cannot pack %s with a 16-bit insn"),
                    CGEN_INSN_NAME (saved_insns[1].insn));
          break;
 
@@ -970,13 +997,13 @@ mep_check_ivc2_scheduling (void)
              slots[SLOTS_P0S] = 2;
            }
          else
-           as_bad ("cannot pack %s and %s together with a 16-bit insn",
+           as_bad (_("cannot pack %s and %s together with a 16-bit insn"),
                    CGEN_INSN_NAME (saved_insns[1].insn),
                    CGEN_INSN_NAME (saved_insns[2].insn));
          break;
 
        default:
-         as_bad ("too many IVC2 insns to pack with a 16-bit core insn");
+         as_bad (_("too many IVC2 insns to pack with a 16-bit core insn"));
          break;
        }
     }
@@ -991,13 +1018,13 @@ mep_check_ivc2_scheduling (void)
        case 2:
          /* The other insn must allow P1.  */
          if (!slot_ok (1, SLOTS_P1))
-           as_bad ("cannot pack %s into slot P1",
+           as_bad (_("cannot pack %s into slot P1"),
                    CGEN_INSN_NAME (saved_insns[1].insn));
          else
            slots[SLOTS_P1] = 1;
          break;
        default:
-         as_bad ("too many IVC2 insns to pack with a 32-bit core insn");
+         as_bad (_("too many IVC2 insns to pack with a 32-bit core insn"));
          break;
        }
     }
@@ -1015,7 +1042,7 @@ mep_check_ivc2_scheduling (void)
          else if (slot_ok (0, SLOTS_P0S))
            slots[SLOTS_P0S] = 0;
          else
-           as_bad ("unable to pack %s by itself?",
+           as_bad (_("unable to pack %s by itself?"),
                    CGEN_INSN_NAME (saved_insns[0].insn));
          break;
 
@@ -1045,13 +1072,13 @@ mep_check_ivc2_scheduling (void)
              slots[SLOTS_P0S] = 1;
            }
          else
-           as_bad ("cannot pack %s and %s together",
+           as_bad (_("cannot pack %s and %s together"),
                    CGEN_INSN_NAME (saved_insns[0].insn),
                    CGEN_INSN_NAME (saved_insns[1].insn));
          break;
 
        default:
-         as_bad ("too many IVC2 insns to pack together");
+         as_bad (_("too many IVC2 insns to pack together"));
          break;
        }
     }
@@ -1070,10 +1097,10 @@ mep_check_ivc2_scheduling (void)
   /* Allocate whatever bytes remain in our insn word.  Adjust the
      pointer to point (as if it were) to the beginning of the whole
      word, so that we don't have to adjust for it elsewhere.  */
-  f = (bfd_byte *) frag_more (8 - corelength / 8);
+  f = (bfd_byte *) frag_more (8 - realcorelength / 8);
   /* Unused slots are filled with NOPs, which happen to be all zeros.  */
-  memset (f, 0, 8 - corelength / 8);
-  f -= corelength / 8;
+  memset (f, 0, 8 - realcorelength / 8);
+  f -= realcorelength / 8;
 
   for (i=1; i<5; i++)
     {
@@ -1144,7 +1171,6 @@ static void
 mep_process_saved_insns (void)
 {
   int i;
-  unsigned j;
 
   gas_cgen_save_fixups (MAX_SAVED_FIXUP_CHAINS - 1);
 
@@ -1164,10 +1190,6 @@ mep_process_saved_insns (void)
          gas_cgen_finish_insn (saved_insns[i].insn, saved_insns[i].buffer,
                                CGEN_FIELDS_BITSIZE (& saved_insns[i].fields),
                                1, NULL);
-         printf("insn[%d] =", i);
-         for (j=0; j<sizeof(saved_insns[i].buffer); j++)
-           printf(" %02x", saved_insns[i].buffer[j]);
-         printf("\n");
        }
     }
   gas_cgen_restore_fixups (MAX_SAVED_FIXUP_CHAINS - 1);
@@ -1504,7 +1526,13 @@ md_estimate_size_before_relax (fragS * fragP, segT segment)
   if (fragP->fr_subtype == 1)
     fragP->fr_subtype = insn_to_subtype (fragP->fr_cgen.insn->base->num);
 
-  if (S_GET_SEGMENT (fragP->fr_symbol) != segment)
+  if (S_GET_SEGMENT (fragP->fr_symbol) != segment
+      || S_IS_WEAK (fragP->fr_symbol)
+#ifdef MEP_IVC2_SUPPORTED
+      || (mep_cop == EF_MEP_COP_IVC2
+         && bfd_get_section_flags (stdoutput, segment) & SEC_MEP_VLIW)
+#endif /* MEP_IVC2_SUPPORTED */
+      )
     {
       int new_insn;
 
@@ -1544,9 +1572,29 @@ md_estimate_size_before_relax (fragS * fragP, segT segment)
        }
     }
 
+#ifdef MEP_IVC2_SUPPORTED
+  if (mep_cop == EF_MEP_COP_IVC2
+      && bfd_get_section_flags (stdoutput, segment) & SEC_MEP_VLIW)
+    return 0;
+#endif /* MEP_IVC2_SUPPORTED */
+
   return subtype_mappings[fragP->fr_subtype].growth;
 }
 
+/* VLIW does relaxing, but not growth.  */
+
+long
+mep_relax_frag (segT segment, fragS *fragP, long stretch)
+{
+  long rv = relax_frag (segment, fragP, stretch);
+#ifdef MEP_IVC2_SUPPORTED
+  if (mep_cop == EF_MEP_COP_IVC2
+      && bfd_get_section_flags (stdoutput, segment) & SEC_MEP_VLIW)
+    return 0;
+#endif
+  return rv;
+}
+
 /* *fragP has been relaxed to its final size, and now needs to have
    the bytes inside it modified to conform to the new size.
 
@@ -1568,19 +1616,29 @@ target_address_for (fragS *frag)
 
 void
 md_convert_frag (bfd *abfd  ATTRIBUTE_UNUSED, 
-                segT sec ATTRIBUTE_UNUSED,
+                segT seg ATTRIBUTE_UNUSED,
                 fragS *fragP)
 {
   int addend, rn, bit = 0;
   int operand;
   int where = fragP->fr_opcode - fragP->fr_literal;
   int e = target_big_endian ? 0 : 1;
+  int core_mode;
+
+#ifdef MEP_IVC2_SUPPORTED
+  if (bfd_get_section_flags (stdoutput, seg) & SEC_MEP_VLIW
+      && mep_cop == EF_MEP_COP_IVC2)
+    core_mode = 0;
+  else
+#endif /* MEP_IVC2_SUPPORTED */
+    core_mode = 1;
 
   addend = target_address_for (fragP) - (fragP->fr_address + where);
 
   if (subtype_mappings[fragP->fr_subtype].insn == -1)
     {
-      fragP->fr_fix += subtype_mappings[fragP->fr_subtype].growth;
+      if (core_mode)
+       fragP->fr_fix += subtype_mappings[fragP->fr_subtype].growth;
       switch (subtype_mappings[fragP->fr_subtype].insn_for_extern)
        {
        case MEP_PSEUDO64_16BITCC:
@@ -1622,7 +1680,8 @@ md_convert_frag (bfd *abfd  ATTRIBUTE_UNUSED,
        break;
 
       case MEP_INSN_BSR24:
-       fragP->fr_fix += 2;
+       if (core_mode)
+         fragP->fr_fix += 2;
        fragP->fr_opcode[0^e] = 0xd8 | ((addend >> 5) & 0x07);
        fragP->fr_opcode[1^e] = 0x09 | ((addend << 3) & 0xf0);
        fragP->fr_opcode[2^e] = 0x00 | ((addend >>16) & 0xff);
@@ -1642,7 +1701,8 @@ md_convert_frag (bfd *abfd  ATTRIBUTE_UNUSED,
           instructions to JMP.  */
        if (addend <= 65535 && addend >= -65536)
          {
-           fragP->fr_fix += 2;
+           if (core_mode)
+             fragP->fr_fix += 2;
            fragP->fr_opcode[0^e] = 0xe0;
            fragP->fr_opcode[1^e] = 0x01;
            fragP->fr_opcode[2^e] = 0x00 | ((addend >> 9) & 0xff);
@@ -1654,7 +1714,8 @@ md_convert_frag (bfd *abfd  ATTRIBUTE_UNUSED,
 
       case MEP_INSN_JMP:
        addend = target_address_for (fragP);
-       fragP->fr_fix += 2;
+       if (core_mode)
+         fragP->fr_fix += 2;
        fragP->fr_opcode[0^e] = 0xd8 | ((addend >> 5) & 0x07);
        fragP->fr_opcode[1^e] = 0x08 | ((addend << 3) & 0xf0);
        fragP->fr_opcode[2^e] = 0x00 | ((addend >>16) & 0xff);
@@ -1674,7 +1735,8 @@ md_convert_frag (bfd *abfd  ATTRIBUTE_UNUSED,
       case MEP_INSN_BEQI:
        if (subtype_mappings[fragP->fr_subtype].growth)
          {
-           fragP->fr_fix += subtype_mappings[fragP->fr_subtype].growth;
+           if (core_mode)
+             fragP->fr_fix += subtype_mappings[fragP->fr_subtype].growth;
            rn = fragP->fr_opcode[0^e] & 0x0f;
            fragP->fr_opcode[0^e] = 0xe0 | rn;
            fragP->fr_opcode[1^e] = bit;
@@ -1700,10 +1762,11 @@ md_convert_frag (bfd *abfd  ATTRIBUTE_UNUSED,
        abort ();
       }
 
-  if (S_GET_SEGMENT (fragP->fr_symbol) != sec
+  if (S_GET_SEGMENT (fragP->fr_symbol) != seg
+      || S_IS_WEAK (fragP->fr_symbol)
       || operand == MEP_OPERAND_PCABS24A2)
     {
-      assert (fragP->fr_cgen.insn != 0);
+      gas_assert (fragP->fr_cgen.insn != 0);
       gas_cgen_record_fixup (fragP,
                             where,
                             fragP->fr_cgen.insn,
@@ -1746,11 +1809,17 @@ md_pcrel_from_section (fixS *fixP, segT sec)
 {
   if (fixP->fx_addsy != (symbolS *) NULL
       && (! S_IS_DEFINED (fixP->fx_addsy)
+         || S_IS_WEAK (fixP->fx_addsy)
          || S_GET_SEGMENT (fixP->fx_addsy) != sec))
     /* The symbol is undefined (or is defined but not in this section).
        Let the linker figure it out.  */
     return 0;
 
+  /* If we've got other reasons for emitting this relocation, let the
+     linker handle pc-rel also.  */
+  if (mep_force_relocation (fixP))
+    return 0;
+
   /* Return the address of the opcode - cgen adjusts for opcode size
      itself, to be consistent with the disassembler, which must do
      so.  */
@@ -1875,7 +1944,7 @@ mep_frob_file ()
       segment_info_type * seginfo;
       int pass;
 
-      assert (FX_OPINFO_R_TYPE (l->fixp) == BFD_RELOC_HI16
+      gas_assert (FX_OPINFO_R_TYPE (l->fixp) == BFD_RELOC_HI16
              || FX_OPINFO_R_TYPE (l->fixp) == BFD_RELOC_LO16);
 
       /* Check quickly whether the next fixup happens to be a matching low.  */
@@ -1915,7 +1984,7 @@ mep_frob_file ()
                  for (pf = &seginfo->fix_root;
                       * pf != l->fixp;
                       pf = & (* pf)->fx_next)
-                   assert (* pf != NULL);
+                   gas_assert (* pf != NULL);
 
                  * pf = l->fixp->fx_next;
 
@@ -1950,6 +2019,9 @@ mep_force_relocation (fixS *fixp)
         || fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
     return 1;
 
+  if (generic_force_reloc (fixp))
+    return 1;
+
   /* Allow branches to global symbols to be resolved at assembly time.
      This is consistent with way relaxable branches are handled, since
      branches to both global and local symbols are relaxed.  It also
@@ -2014,8 +2086,8 @@ mep_elf_section_letter (int letter, char **ptrmsg)
   if (letter == 'v')
     return SHF_MEP_VLIW;
 
-  *ptrmsg = _("Bad .section directive: want a,v,w,x,M,S in string");
-  return 0;
+  *ptrmsg = _("bad .section directive: want a,v,w,x,M,S in string");
+  return -1;
 }
 
 flagword
This page took 0.030439 seconds and 4 git commands to generate.