Back to index

cell-binutils  2.17cvs20070401
tc-mep.c
Go to the documentation of this file.
00001 /* tc-mep.c -- Assembler for the Toshiba Media Processor.
00002    Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation.
00003 
00004    This file is part of GAS, the GNU Assembler.
00005 
00006    GAS is free software; you can redistribute it and/or modify
00007    it under the terms of the GNU General Public License as published by
00008    the Free Software Foundation; either version 2, or (at your option)
00009    any later version.
00010 
00011    GAS is distributed in the hope that it will be useful,
00012    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014    GNU General Public License for more details.
00015 
00016    You should have received a copy of the GNU General Public License
00017    along with GAS; see the file COPYING.  If not, write to
00018    the Free Software Foundation, 51 Franklin Street, Fifth Floor,
00019    Boston, MA 02110-1301, USA.  */
00020 
00021 #include <stdio.h>
00022 #include "as.h"
00023 #include "dwarf2dbg.h"
00024 #include "subsegs.h"
00025 #include "symcat.h"
00026 #include "opcodes/mep-desc.h"
00027 #include "opcodes/mep-opc.h"
00028 #include "cgen.h"
00029 #include "elf/common.h"
00030 #include "elf/mep.h"
00031 #include "libbfd.h"
00032 #include "xregex.h"
00033 
00034 /* Structure to hold all of the different components describing
00035    an individual instruction.  */
00036 typedef struct
00037 {
00038   const CGEN_INSN *  insn;
00039   const CGEN_INSN *  orig_insn;
00040   CGEN_FIELDS        fields;
00041 #if CGEN_INT_INSN_P
00042   CGEN_INSN_INT         buffer [1];
00043 #define INSN_VALUE(buf) (*(buf))
00044 #else
00045   unsigned char         buffer [CGEN_MAX_INSN_SIZE];
00046 #define INSN_VALUE(buf) (buf)
00047 #endif
00048   char *             addr;
00049   fragS *            frag;
00050   int                   num_fixups;
00051   fixS *                fixups [GAS_CGEN_MAX_FIXUPS];
00052   int                   indices [MAX_OPERAND_INSTANCES];
00053 } mep_insn;
00054 
00055 static int mode = CORE; /* Start in core mode. */
00056 static int pluspresent = 0;
00057 static int allow_disabled_registers = 0;
00058 static int library_flag = 0;
00059 
00060 /* We're going to need to store all of the instructions along with
00061    their fixups so that we can parallelization grouping rules. */
00062 
00063 static mep_insn saved_insns[MAX_SAVED_FIXUP_CHAINS];
00064 static int num_insns_saved = 0;
00065 
00066 const char comment_chars[]        = "#";
00067 const char line_comment_chars[]   = ";#";
00068 const char line_separator_chars[] = ";";
00069 const char EXP_CHARS[]            = "eE";
00070 const char FLT_CHARS[]            = "dD";
00071 
00072 static void mep_switch_to_vliw_mode (int);
00073 static void mep_switch_to_core_mode (int);
00074 static void mep_s_vtext (int);
00075 static void mep_noregerr (int);
00076 
00077 /* The target specific pseudo-ops which we support.  */
00078 const pseudo_typeS md_pseudo_table[] =
00079 {
00080   { "word",   cons,                          4 },
00081   { "file",   (void (*) (int)) dwarf2_directive_file,          0 },
00082   { "loc",    dwarf2_directive_loc,       0 },
00083   { "vliw",   mep_switch_to_vliw_mode,    0 },
00084   { "core",   mep_switch_to_core_mode,    0 },
00085   { "vtext",  mep_s_vtext,                0 },
00086   { "noregerr",      mep_noregerr,               0 },
00087   { NULL,     NULL,                       0 }
00088 };
00089 
00090 /* Relocations against symbols are done in two
00091    parts, with a HI relocation and a LO relocation.  Each relocation
00092    has only 16 bits of space to store an addend.  This means that in
00093    order for the linker to handle carries correctly, it must be able
00094    to locate both the HI and the LO relocation.  This means that the
00095    relocations must appear in order in the relocation table.
00096 
00097    In order to implement this, we keep track of each unmatched HI
00098    relocation.  We then sort them so that they immediately precede the
00099    corresponding LO relocation. */
00100 
00101 struct mep_hi_fixup
00102 {
00103   struct mep_hi_fixup * next;      /* Next HI fixup.  */
00104   fixS * fixp;                     /* This fixup.  */
00105   segT seg;                 /* The section this fixup is in.  */
00106 };
00107 
00108 /* The list of unmatched HI relocs.  */
00109 static struct mep_hi_fixup * mep_hi_fixup_list;
00110 
00111 
00112 #define OPTION_EB           (OPTION_MD_BASE + 0)
00113 #define OPTION_EL           (OPTION_MD_BASE + 1)
00114 #define OPTION_CONFIG              (OPTION_MD_BASE + 2)
00115 #define OPTION_AVERAGE             (OPTION_MD_BASE + 3)
00116 #define OPTION_NOAVERAGE    (OPTION_MD_BASE + 4)
00117 #define OPTION_MULT         (OPTION_MD_BASE + 5)
00118 #define OPTION_NOMULT              (OPTION_MD_BASE + 6)
00119 #define OPTION_DIV          (OPTION_MD_BASE + 7)
00120 #define OPTION_NODIV        (OPTION_MD_BASE + 8)
00121 #define OPTION_BITOPS              (OPTION_MD_BASE + 9)
00122 #define OPTION_NOBITOPS            (OPTION_MD_BASE + 10)
00123 #define OPTION_LEADZ        (OPTION_MD_BASE + 11)
00124 #define OPTION_NOLEADZ             (OPTION_MD_BASE + 12)
00125 #define OPTION_ABSDIFF             (OPTION_MD_BASE + 13)
00126 #define OPTION_NOABSDIFF    (OPTION_MD_BASE + 14)
00127 #define OPTION_MINMAX              (OPTION_MD_BASE + 15)
00128 #define OPTION_NOMINMAX            (OPTION_MD_BASE + 16)
00129 #define OPTION_CLIP         (OPTION_MD_BASE + 17)
00130 #define OPTION_NOCLIP              (OPTION_MD_BASE + 18)
00131 #define OPTION_SATUR        (OPTION_MD_BASE + 19)
00132 #define OPTION_NOSATUR             (OPTION_MD_BASE + 20)
00133 #define OPTION_COP32        (OPTION_MD_BASE + 21)
00134 #define OPTION_REPEAT              (OPTION_MD_BASE + 25)
00135 #define OPTION_NOREPEAT            (OPTION_MD_BASE + 26)
00136 #define OPTION_DEBUG        (OPTION_MD_BASE + 27)
00137 #define OPTION_NODEBUG             (OPTION_MD_BASE + 28)
00138 #define OPTION_LIBRARY             (OPTION_MD_BASE + 29)
00139 
00140 struct option md_longopts[] = {
00141   { "EB",          no_argument, NULL, OPTION_EB},
00142   { "EL",          no_argument, NULL, OPTION_EL},
00143   { "mconfig",     required_argument, NULL, OPTION_CONFIG},
00144   { "maverage",    no_argument, NULL, OPTION_AVERAGE},
00145   { "mno-average", no_argument, NULL, OPTION_NOAVERAGE},
00146   { "mmult",       no_argument, NULL, OPTION_MULT},
00147   { "mno-mult",    no_argument, NULL, OPTION_NOMULT},
00148   { "mdiv",        no_argument, NULL, OPTION_DIV},
00149   { "mno-div",     no_argument, NULL, OPTION_NODIV},
00150   { "mbitops",     no_argument, NULL, OPTION_BITOPS},
00151   { "mno-bitops",  no_argument, NULL, OPTION_NOBITOPS},
00152   { "mleadz",      no_argument, NULL, OPTION_LEADZ},
00153   { "mno-leadz",   no_argument, NULL, OPTION_NOLEADZ},
00154   { "mabsdiff",    no_argument, NULL, OPTION_ABSDIFF},
00155   { "mno-absdiff", no_argument, NULL, OPTION_NOABSDIFF},
00156   { "mminmax",     no_argument, NULL, OPTION_MINMAX},
00157   { "mno-minmax",  no_argument, NULL, OPTION_NOMINMAX},
00158   { "mclip",       no_argument, NULL, OPTION_CLIP},
00159   { "mno-clip",    no_argument, NULL, OPTION_NOCLIP},
00160   { "msatur",      no_argument, NULL, OPTION_SATUR},
00161   { "mno-satur",   no_argument, NULL, OPTION_NOSATUR},
00162   { "mcop32",    no_argument, NULL, OPTION_COP32},
00163   { "mdebug",      no_argument, NULL, OPTION_DEBUG},
00164   { "mno-debug",   no_argument, NULL, OPTION_NODEBUG},
00165   { "mlibrary",    no_argument, NULL, OPTION_LIBRARY},
00166   { NULL, 0, NULL, 0 } };
00167 size_t md_longopts_size = sizeof (md_longopts);
00168 
00169 const char * md_shortopts = "";
00170 static int optbits = 0;
00171 static int optbitset = 0;
00172 
00173 int
00174 md_parse_option (int c, char *arg ATTRIBUTE_UNUSED)
00175 {
00176   int i, idx;
00177   switch (c)
00178     {
00179     case OPTION_EB:
00180       target_big_endian = 1;
00181       break;
00182     case OPTION_EL:
00183       target_big_endian = 0;
00184       break;
00185     case OPTION_CONFIG:
00186       idx = 0;
00187       for (i=1; mep_config_map[i].name; i++)
00188        if (strcmp (mep_config_map[i].name, arg) == 0)
00189          {
00190            idx = i;
00191            break;
00192          }
00193       if (!idx)
00194        {
00195          fprintf (stderr, "Error: unknown configuration %s\n", arg);
00196          return 0;
00197        }
00198       mep_config_index = idx;
00199       target_big_endian = mep_config_map[idx].big_endian;
00200       break;
00201     case OPTION_AVERAGE:
00202       optbits |= 1 << CGEN_INSN_OPTIONAL_AVE_INSN;
00203       optbitset |= 1 << CGEN_INSN_OPTIONAL_AVE_INSN;
00204       break;
00205     case OPTION_NOAVERAGE:
00206       optbits &= ~(1 << CGEN_INSN_OPTIONAL_AVE_INSN);
00207       optbitset |= 1 << CGEN_INSN_OPTIONAL_AVE_INSN;
00208       break;
00209     case OPTION_MULT:
00210       optbits |= 1 << CGEN_INSN_OPTIONAL_MUL_INSN;
00211       optbitset |= 1 << CGEN_INSN_OPTIONAL_MUL_INSN;
00212       break;
00213     case OPTION_NOMULT:
00214       optbits &= ~(1 << CGEN_INSN_OPTIONAL_MUL_INSN);
00215       optbitset |= 1 << CGEN_INSN_OPTIONAL_MUL_INSN;
00216       break;
00217     case OPTION_DIV:
00218       optbits |= 1 << CGEN_INSN_OPTIONAL_DIV_INSN;
00219       optbitset |= 1 << CGEN_INSN_OPTIONAL_DIV_INSN;
00220       break;
00221     case OPTION_NODIV:
00222       optbits &= ~(1 << CGEN_INSN_OPTIONAL_DIV_INSN);
00223       optbitset |= 1 << CGEN_INSN_OPTIONAL_DIV_INSN;
00224       break;
00225     case OPTION_BITOPS:
00226       optbits |= 1 << CGEN_INSN_OPTIONAL_BIT_INSN;
00227       optbitset |= 1 << CGEN_INSN_OPTIONAL_BIT_INSN;
00228       break;
00229     case OPTION_NOBITOPS:
00230       optbits &= ~(1 << CGEN_INSN_OPTIONAL_BIT_INSN);
00231       optbitset |= 1 << CGEN_INSN_OPTIONAL_BIT_INSN;
00232       break;
00233     case OPTION_LEADZ:
00234       optbits |= 1 << CGEN_INSN_OPTIONAL_LDZ_INSN;
00235       optbitset |= 1 << CGEN_INSN_OPTIONAL_LDZ_INSN;
00236       break;
00237     case OPTION_NOLEADZ:
00238       optbits &= ~(1 << CGEN_INSN_OPTIONAL_LDZ_INSN);
00239       optbitset |= 1 << CGEN_INSN_OPTIONAL_LDZ_INSN;
00240       break;
00241     case OPTION_ABSDIFF:
00242       optbits |= 1 << CGEN_INSN_OPTIONAL_ABS_INSN;
00243       optbitset |= 1 << CGEN_INSN_OPTIONAL_ABS_INSN;
00244       break;
00245     case OPTION_NOABSDIFF:
00246       optbits &= ~(1 << CGEN_INSN_OPTIONAL_ABS_INSN);
00247       optbitset |= 1 << CGEN_INSN_OPTIONAL_ABS_INSN;
00248       break;
00249     case OPTION_MINMAX:
00250       optbits |= 1 << CGEN_INSN_OPTIONAL_MINMAX_INSN;
00251       optbitset |= 1 << CGEN_INSN_OPTIONAL_MINMAX_INSN;
00252       break;
00253     case OPTION_NOMINMAX:
00254       optbits &= ~(1 << CGEN_INSN_OPTIONAL_MINMAX_INSN);
00255       optbitset |= 1 << CGEN_INSN_OPTIONAL_MINMAX_INSN;
00256       break;
00257     case OPTION_CLIP:
00258       optbits |= 1 << CGEN_INSN_OPTIONAL_CLIP_INSN;
00259       optbitset |= 1 << CGEN_INSN_OPTIONAL_CLIP_INSN;
00260       break;
00261     case OPTION_NOCLIP:
00262       optbits &= ~(1 << CGEN_INSN_OPTIONAL_CLIP_INSN);
00263       optbitset |= 1 << CGEN_INSN_OPTIONAL_CLIP_INSN;
00264       break;
00265     case OPTION_SATUR:
00266       optbits |= 1 << CGEN_INSN_OPTIONAL_SAT_INSN;
00267       optbitset |= 1 << CGEN_INSN_OPTIONAL_SAT_INSN;
00268       break;
00269     case OPTION_NOSATUR:
00270       optbits &= ~(1 << CGEN_INSN_OPTIONAL_SAT_INSN);
00271       optbitset |= 1 << CGEN_INSN_OPTIONAL_SAT_INSN;
00272       break;
00273     case OPTION_COP32:
00274       optbits |= 1 << CGEN_INSN_OPTIONAL_CP_INSN;
00275       optbitset |= 1 << CGEN_INSN_OPTIONAL_CP_INSN;
00276       break;
00277     case OPTION_DEBUG:
00278       optbits |= 1 << CGEN_INSN_OPTIONAL_DEBUG_INSN;
00279       optbitset |= 1 << CGEN_INSN_OPTIONAL_DEBUG_INSN;
00280       break;
00281     case OPTION_NODEBUG:
00282       optbits &= ~(1 << CGEN_INSN_OPTIONAL_DEBUG_INSN);
00283       optbitset |= 1 << CGEN_INSN_OPTIONAL_DEBUG_INSN;
00284       break;
00285     case OPTION_LIBRARY:
00286       library_flag = EF_MEP_LIBRARY;
00287       break;
00288     case OPTION_REPEAT:
00289     case OPTION_NOREPEAT:
00290       break;
00291     default:
00292       return 0;
00293     }
00294   return 1;
00295 }
00296 
00297 void
00298 md_show_usage (FILE *stream)
00299 {
00300   fprintf (stream, _("MeP specific command line options:\n\
00301   -EB                     assemble for a big endian system (default)\n\
00302   -EL                     assemble for a little endian system\n\
00303   -mconfig=<name>         specify a chip configuration to use\n\
00304   -maverage -mno-average -mmult -mno-mult -mdiv -mno-div\n\
00305   -mbitops -mno-bitops -mleadz -mno-leadz -mabsdiff -mno-absdiff\n\
00306   -mminmax -mno-minmax -mclip -mno-clip -msatur -mno-satur -mcop32\n\
00307                           enable/disable the given opcodes\n\
00308 \n\
00309   If -mconfig is given, the other -m options modify it.  Otherwise,\n\
00310   if no -m options are given, all core opcodes are enabled;\n\
00311   if any enabling -m options are given, only those are enabled;\n\
00312   if only disabling -m options are given, only those are disabled.\n\
00313 "));
00314   if (mep_config_map[1].name)
00315     {
00316       int i;
00317       fprintf (stream, "  -mconfig=STR            specify the configuration to use\n");
00318       fprintf (stream, "  Configurations:");
00319       for (i=0; mep_config_map[i].name; i++)
00320        fprintf (stream, " %s", mep_config_map[i].name);
00321       fprintf (stream, "\n");
00322     }
00323 }
00324 
00325 
00326 
00327 static void
00328 mep_check_for_disabled_registers (mep_insn *insn)
00329 {
00330   static int initted = 0;
00331   static int has_mul_div = 0;
00332   static int has_cop = 0;
00333   static int has_debug = 0;
00334   unsigned int b, r;
00335 
00336   if (allow_disabled_registers)
00337     return;
00338 
00339 #if !CGEN_INT_INSN_P
00340   if (target_big_endian)
00341     b = insn->buffer[0] * 256 + insn->buffer[1];
00342   else
00343     b = insn->buffer[1] * 256 + insn->buffer[0];
00344 #else
00345   b = insn->buffer[0];
00346 #endif
00347 
00348   if ((b & 0xfffff00e) == 0x7008 /* stc */
00349       || (b & 0xfffff00e) == 0x700a /* ldc */)
00350     {
00351       if (!initted)
00352        {
00353          initted = 1;
00354          if ((MEP_OMASK & (1 << CGEN_INSN_OPTIONAL_MUL_INSN))
00355              || (MEP_OMASK & (1 << CGEN_INSN_OPTIONAL_DIV_INSN)))
00356            has_mul_div = 1;
00357          if (MEP_OMASK & (1 << CGEN_INSN_OPTIONAL_DEBUG_INSN))
00358            has_debug = 1;
00359          if (MEP_OMASK & (1 << CGEN_INSN_OPTIONAL_CP_INSN))
00360            has_cop = 1;
00361        }
00362 
00363       r = ((b & 0x00f0) >> 4) | ((b & 0x0001) << 4);
00364       switch (r)
00365        {
00366        case 7: /* $hi */
00367        case 8: /* $lo */
00368          if (!has_mul_div)
00369            as_bad ("$hi and $lo are disabled when MUL and DIV are off");
00370          break;
00371        case 12: /* $mb0 */
00372        case 13: /* $me0 */
00373        case 14: /* $mb1 */
00374        case 15: /* $me1 */
00375          if (!has_cop)
00376            as_bad ("$mb0, $me0, $mb1, and $me1 are disabled when COP is off");
00377          break;
00378        case 24: /* $dbg */
00379        case 25: /* $depc */
00380          if (!has_debug)
00381            as_bad ("$dbg and $depc are disabled when DEBUG is off");
00382          break;
00383        }
00384     }
00385 }
00386 
00387 static int
00388 mep_machine (void)
00389 {
00390   switch (MEP_CPU)
00391     {
00392     default: break;
00393     case EF_MEP_CPU_C2: return bfd_mach_mep;
00394     case EF_MEP_CPU_C3: return bfd_mach_mep;
00395     case EF_MEP_CPU_C4: return bfd_mach_mep;
00396     case EF_MEP_CPU_H1: return bfd_mach_mep_h1;
00397     }
00398 
00399   return bfd_mach_mep;
00400 }
00401 
00402 /* The MeP version of the cgen parse_operand function.  The only difference
00403    from the standard version is that we want to avoid treating '$foo' and
00404    '($foo...)' as references to a symbol called '$foo'.  The chances are
00405    that '$foo' is really a misspelt register.  */
00406 
00407 static const char *
00408 mep_parse_operand (CGEN_CPU_DESC cd, enum cgen_parse_operand_type want,
00409                  const char **strP, int opindex, int opinfo,
00410                  enum cgen_parse_operand_result *resultP, bfd_vma *valueP)
00411 {
00412   if (want == CGEN_PARSE_OPERAND_INTEGER || want == CGEN_PARSE_OPERAND_ADDRESS)
00413     {
00414       const char *next;
00415 
00416       next = *strP;
00417       while (*next == '(')
00418        next++;
00419       if (*next == '$')
00420        return "Not a valid literal";
00421     }
00422   return gas_cgen_parse_operand (cd, want, strP, opindex, opinfo,
00423                              resultP, valueP);
00424 }
00425 
00426 void
00427 md_begin ()
00428 {
00429   /* Initialize the `cgen' interface.  */
00430 
00431   /* If the user specifies no options, we default to allowing
00432      everything.  If the user specifies any enabling options, we
00433      default to allowing only what is specified.  If the user
00434      specifies only disabling options, we only disable what is
00435      specified.  If the user specifies options and a config, the
00436      options modify the config.  */
00437   if (optbits && mep_config_index == 0)
00438     MEP_OMASK = optbits;
00439   else
00440     MEP_OMASK = (MEP_OMASK & ~optbitset) | optbits;
00441 
00442   /* Set the machine number and endian.  */
00443   gas_cgen_cpu_desc = mep_cgen_cpu_open (CGEN_CPU_OPEN_MACHS, 0,
00444                                     CGEN_CPU_OPEN_ENDIAN,
00445                                     target_big_endian
00446                                     ? CGEN_ENDIAN_BIG
00447                                     : CGEN_ENDIAN_LITTLE,
00448                                     CGEN_CPU_OPEN_ISAS, 0,
00449                                     CGEN_CPU_OPEN_END);
00450   mep_cgen_init_asm (gas_cgen_cpu_desc);
00451 
00452   /* This is a callback from cgen to gas to parse operands.  */
00453   cgen_set_parse_operand_fn (gas_cgen_cpu_desc, mep_parse_operand);
00454 
00455   /* Identify the architecture.  */
00456   bfd_default_set_arch_mach (stdoutput, bfd_arch_mep, mep_machine ());
00457 
00458   /* Store the configuration number and core.  */
00459   bfd_set_private_flags (stdoutput, MEP_CPU | MEP_CONFIG | library_flag);
00460 
00461   /* Initialize the array we'll be using to store fixups.  */
00462   gas_cgen_initialize_saved_fixups_array();
00463 }
00464 
00465 /* Variant of mep_cgen_assemble_insn.  Assemble insn STR of cpu CD as a 
00466    coprocessor instruction, if possible, into FIELDS, BUF, and INSN.  */
00467 
00468 static const CGEN_INSN *
00469 mep_cgen_assemble_cop_insn (CGEN_CPU_DESC cd,
00470                          const char *str,
00471                          CGEN_FIELDS *fields,
00472                          CGEN_INSN_BYTES_PTR buf,
00473                          const struct cgen_insn *pinsn)
00474 {
00475   const char *start;
00476   CGEN_INSN_LIST *ilist;
00477   const char *errmsg = NULL;
00478 
00479   /* The instructions are stored in hashed lists. */
00480   ilist = CGEN_ASM_LOOKUP_INSN (gas_cgen_cpu_desc, 
00481                             CGEN_INSN_MNEMONIC (pinsn));
00482 
00483   start = str;
00484   for ( ; ilist != NULL ; ilist = CGEN_ASM_NEXT_INSN (ilist))
00485     {
00486       const CGEN_INSN *insn = ilist->insn;
00487       if (strcmp (CGEN_INSN_MNEMONIC (ilist->insn), 
00488                 CGEN_INSN_MNEMONIC (pinsn)) == 0
00489          && MEP_INSN_COP_P (ilist->insn)
00490          && mep_cgen_insn_supported (cd, insn))
00491        {
00492          str = start;
00493 
00494          /* skip this insn if str doesn't look right lexically */
00495          if (CGEN_INSN_RX (insn) != NULL &&
00496              regexec ((regex_t *) CGEN_INSN_RX (insn), str, 0, NULL, 0) == REG_NOMATCH)
00497            continue;
00498 
00499          /* Allow parse/insert handlers to obtain length of insn.  */
00500          CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn);
00501 
00502          errmsg = CGEN_PARSE_FN (cd, insn) (cd, insn, & str, fields);
00503          if (errmsg != NULL)
00504            continue;
00505          
00506          errmsg = CGEN_INSERT_FN (cd, insn) (cd, insn, fields, buf,
00507                                          (bfd_vma) 0);
00508          if (errmsg != NULL)
00509            continue;
00510 
00511          return insn;
00512        }
00513     }
00514   return pinsn;
00515 }
00516 
00517 static void
00518 mep_save_insn (mep_insn insn)
00519 {
00520   /* Consider change MAX_SAVED_FIXUP_CHAINS to MAX_PARALLEL_INSNS. */
00521   if (num_insns_saved < 0 || num_insns_saved >= MAX_SAVED_FIXUP_CHAINS)
00522     {
00523       as_fatal("index into saved_insns[] out of bounds.");
00524       return;
00525     }
00526   saved_insns[num_insns_saved] = insn;
00527   gas_cgen_save_fixups(num_insns_saved);
00528   num_insns_saved++;
00529 }
00530 
00531 static void
00532 mep_check_parallel32_scheduling (void)
00533 {
00534   int insn0iscopro, insn1iscopro, insn0length, insn1length;
00535 
00536   /* More than two instructions means that either someone is referring to
00537      an internally parallel core or an internally parallel coprocessor,
00538      neither of which are supported at this time.  */
00539   if ( num_insns_saved > 2 )
00540     as_fatal("Internally paralled cores and coprocessors not supported.");
00541 
00542   /* If there are no insns saved, that's ok.  Just return.  This will
00543      happen when mep_process_saved_insns is called when the end of the
00544      source file is reached and there are no insns left to be processed.  */
00545   if (num_insns_saved == 0)
00546     return;
00547 
00548   /* Check some of the attributes of the first insn.  */
00549   insn0iscopro = MEP_INSN_COP_P (saved_insns[0].insn);
00550   insn0length = CGEN_FIELDS_BITSIZE (& saved_insns[0].fields);
00551 
00552   if (num_insns_saved == 2)
00553     {
00554       /* Check some of the attributes of the first insn.  */
00555       insn1iscopro = MEP_INSN_COP_P (saved_insns[1].insn);
00556       insn1length = CGEN_FIELDS_BITSIZE (& saved_insns[1].fields);
00557 
00558       if ((insn0iscopro && !insn1iscopro)
00559           || (insn1iscopro && !insn0iscopro))
00560        {
00561           /* We have one core and one copro insn.  If their sizes
00562              add up to 32, then the combination is valid.  */
00563          if (insn0length + insn1length == 32)
00564            return;
00565           else
00566            as_bad ("core and copro insn lengths must total 32 bits.");
00567        }
00568       else
00569         as_bad ("vliw group must consist of 1 core and 1 copro insn."); 
00570     }
00571   else
00572     {
00573       /* If we arrive here, we have one saved instruction.  There are a
00574         number of possible cases:
00575 
00576         1.  The instruction is a 32 bit core or coprocessor insn and
00577              can be executed by itself.  Valid.
00578 
00579          2.  The instrucion is a core instruction for which a cop nop
00580              exists.  In this case, insert the cop nop into the saved
00581              insn array after the core insn and return.  Valid.
00582 
00583          3.  The instruction is a coprocessor insn for which a core nop
00584              exists.  In this case, move the coprocessor insn to the
00585              second element of the array and put the nop in the first
00586             element then return.  Valid.
00587 
00588          4. The instruction is a core or coprocessor instruction for
00589             which there is no matching coprocessor or core nop to use
00590            to form a valid vliw insn combination.  In this case, we
00591            we have to abort.  */
00592 
00593       if (insn0length > 32)
00594        as_fatal ("Cannot use 48- or 64-bit insns with a 32 bit datapath.");
00595 
00596       if (insn0length == 32)
00597        return;
00598 
00599       /* Insn is smaller than datapath.  If there are no matching
00600          nops for this insn, then terminate assembly.  */
00601       if (CGEN_INSN_ATTR_VALUE (saved_insns[0].insn,
00602                                 CGEN_INSN_VLIW32_NO_MATCHING_NOP))
00603        as_fatal ("No valid nop.");
00604 
00605       /* At this point we know that we have a single 16-bit insn that has 
00606         a matching nop.  We have to assemble it and put it into the saved 
00607          insn and fixup chain arrays. */
00608 
00609       if (insn0iscopro)
00610        {
00611           char *errmsg;
00612           mep_insn insn;
00613          
00614           /* Move the insn and it's fixups to the second element of the
00615              saved insns arrary and insert a 16 bit core nope into the
00616              first element. */
00617              insn.insn = mep_cgen_assemble_insn (gas_cgen_cpu_desc, "nop",
00618                                                  &insn.fields, insn.buffer,
00619                                                  &errmsg);
00620              if (!insn.insn)
00621                {
00622                  as_bad ("%s", errmsg);
00623                  return;
00624                }
00625 
00626              /* Move the insn in element 0 to element 1 and insert the
00627                  nop into element 0.  Move the fixups in element 0 to
00628                  element 1 and save the current fixups to element 0.  
00629                  Really there aren't any fixups at this point because we're
00630                  inserting a nop but we might as well be general so that
00631                  if there's ever a need to insert a general insn, we'll
00632                  have an example. */
00633               saved_insns[1] = saved_insns[0];
00634               saved_insns[0] = insn;
00635               num_insns_saved++;
00636               gas_cgen_swap_fixups (0);
00637               gas_cgen_save_fixups (1);
00638        }
00639       else
00640        {
00641           char * errmsg;
00642           mep_insn insn;
00643          int insn_num = saved_insns[0].insn->base->num;
00644 
00645          /* Use 32 bit branches and skip the nop.  */
00646          if (insn_num == MEP_INSN_BSR12
00647              || insn_num == MEP_INSN_BEQZ
00648              || insn_num == MEP_INSN_BNEZ)
00649            return;
00650 
00651           /* Insert a 16-bit coprocessor nop.  Note that at the time */
00652           /* this was done, no 16-bit coprocessor nop was defined.   */
00653          insn.insn = mep_cgen_assemble_insn (gas_cgen_cpu_desc, "cpnop16",
00654                                          &insn.fields, insn.buffer,
00655                                          &errmsg);
00656           if (!insn.insn)
00657             {
00658               as_bad ("%s", errmsg);
00659               return;
00660             }
00661 
00662           /* Now put the insn and fixups into the arrays.  */
00663           mep_save_insn (insn);
00664        }
00665     }
00666 }
00667 
00668 static void
00669 mep_check_parallel64_scheduling (void)
00670 {
00671   int insn0iscopro, insn1iscopro, insn0length, insn1length;
00672 
00673   /* More than two instructions means that someone is referring to an
00674      internally parallel core or an internally parallel coprocessor.  */
00675   /* These are not currently supported.  */
00676   if (num_insns_saved > 2)
00677     as_fatal ("Internally parallel cores of coprocessors not supported.");
00678 
00679   /* If there are no insns saved, that's ok.  Just return.  This will
00680      happen when mep_process_saved_insns is called when the end of the
00681      source file is reached and there are no insns left to be processed.  */
00682   if (num_insns_saved == 0)
00683     return;
00684 
00685   /* Check some of the attributes of the first insn.  */
00686   insn0iscopro = MEP_INSN_COP_P (saved_insns[0].insn);
00687   insn0length = CGEN_FIELDS_BITSIZE (& saved_insns[0].fields);
00688 
00689   if (num_insns_saved == 2)
00690     {
00691       /* Check some of the attributes of the first insn. */
00692       insn1iscopro = MEP_INSN_COP_P (saved_insns[1].insn);
00693       insn1length = CGEN_FIELDS_BITSIZE (& saved_insns[1].fields);
00694 
00695       if ((insn0iscopro && !insn1iscopro)
00696          || (insn1iscopro && !insn0iscopro))
00697        {
00698          /* We have one core and one copro insn.  If their sizes
00699             add up to 64, then the combination is valid.  */
00700          if (insn0length + insn1length == 64)
00701             return;
00702          else
00703             as_bad ("core and copro insn lengths must total 64 bits.");
00704        }
00705       else
00706         as_bad ("vliw group must consist of 1 core and 1 copro insn.");
00707     }
00708   else
00709     {
00710       /* If we arrive here, we have one saved instruction.  There are a
00711         number of possible cases:
00712 
00713          1.  The instruction is a 64 bit coprocessor insn and can be
00714              executed by itself.  Valid.
00715 
00716          2.  The instrucion is a core instruction for which a cop nop
00717              exists.  In this case, insert the cop nop into the saved
00718              insn array after the core insn and return.  Valid.
00719 
00720          3.  The instruction is a coprocessor insn for which a core nop
00721              exists.  In this case, move the coprocessor insn to the
00722              second element of the array and put the nop in the first
00723              element then return.  Valid.
00724 
00725          4.  The instruction is a core or coprocessor instruction for
00726              which there is no matching coprocessor or core nop to use
00727              to form a valid vliw insn combination.  In this case, we
00728             we have to abort.  */
00729 
00730       /* If the insn is 64 bits long, it can run alone.  The size check
00731         is done indepependantly of whether the insn is core or copro
00732         in case 64 bit coprocessor insns are added later.  */
00733       if (insn0length == 64)
00734         return;
00735 
00736       /* Insn is smaller than datapath.  If there are no matching
00737         nops for this insn, then terminate assembly.  */
00738       if (CGEN_INSN_ATTR_VALUE (saved_insns[0].insn,
00739                             CGEN_INSN_VLIW64_NO_MATCHING_NOP))
00740        as_fatal ("No valid nop.");
00741 
00742       if (insn0iscopro)
00743        {
00744          char *errmsg;
00745          mep_insn insn;
00746           int i;
00747 
00748           /* Initialize the insn buffer.  */
00749           for (i = 0; i < 64; i++)
00750              insn.buffer[i] = '\0';
00751 
00752          /* We have a coprocessor insn.  At this point in time there
00753             are is 32-bit core nop.  There is only a 16-bit core
00754             nop.  The idea is to allow for a relatively arbitrary
00755             coprocessor to be specified.  We aren't looking at
00756             trying to cover future changes in the core at this time
00757             since it is assumed that the core will remain fairly
00758             static.  If there ever are 32 or 48 bit core nops added,
00759             they will require entries below.  */
00760 
00761          if (insn0length == 48)
00762            {
00763              /* Move the insn and fixups to the second element of the
00764                arrays then assemble and insert a 16 bit core nop.  */
00765              insn.insn = mep_cgen_assemble_insn (gas_cgen_cpu_desc, "nop",
00766                                             & insn.fields, insn.buffer,
00767                                             & errmsg);
00768            }
00769           else
00770             {
00771               /* If this is reached, then we have a single coprocessor
00772                  insn that is not 48 bits long, but for which the assembler
00773                  thinks there is a matching core nop.  If a 32-bit core
00774                  nop has been added, then make the necessary changes and
00775                  handle its assembly and insertion here.  Otherwise,
00776                  go figure out why either:
00777               
00778                  1. The assembler thinks that there is a 32-bit core nop
00779                     to match a 32-bit coprocessor insn, or
00780                  2. The assembler thinks that there is a 48-bit core nop
00781                     to match a 16-bit coprocessor insn.  */
00782 
00783               as_fatal ("Assembler expects a non-existent core nop.");
00784             }
00785 
00786         if (!insn.insn)
00787           {
00788             as_bad ("%s", errmsg);
00789             return;
00790           }
00791 
00792          /* Move the insn in element 0 to element 1 and insert the
00793             nop into element 0.  Move the fixups in element 0 to
00794             element 1 and save the current fixups to element 0. 
00795            Really there aren't any fixups at this point because we're
00796            inserting a nop but we might as well be general so that
00797            if there's ever a need to insert a general insn, we'll
00798            have an example. */
00799 
00800          saved_insns[1] = saved_insns[0];
00801          saved_insns[0] = insn;
00802          num_insns_saved++;
00803          gas_cgen_swap_fixups(0);
00804          gas_cgen_save_fixups(1);
00805 
00806        }
00807       else
00808        {
00809          char * errmsg;
00810          mep_insn insn;
00811           int i;
00812 
00813           /* Initialize the insn buffer */
00814           for (i = 0; i < 64; i++)
00815              insn.buffer[i] = '\0';
00816 
00817          /* We have a core insn.  We have to handle all possible nop
00818             lengths.  If a coprocessor doesn't have a nop of a certain
00819             length but there exists core insns that when combined with
00820              a nop of that length would fill the datapath, those core
00821              insns will be flagged with the VLIW_NO_CORRESPONDING_NOP
00822              attribute.  That will ensure that when used in a way that
00823              requires a nop to be inserted, assembly will terminate
00824              before reaching this section of code.  This guarantees
00825              that cases below which would result in the attempted
00826              insertion of nop that doesn't exist will never be entered.  */
00827          if (insn0length == 16)
00828            {
00829              /* Insert 48 bit coprocessor nop.          */
00830              /* Assemble it and put it into the arrays. */
00831              insn.insn = mep_cgen_assemble_insn (gas_cgen_cpu_desc, "cpnop48",
00832                                             &insn.fields, insn.buffer,
00833                                             &errmsg);
00834            }
00835          else if (insn0length == 32)
00836            {
00837              /* Insert 32 bit coprocessor nop. */
00838              insn.insn = mep_cgen_assemble_insn (gas_cgen_cpu_desc, "cpnop32",
00839                                             &insn.fields, insn.buffer,
00840                                             &errmsg);
00841            }
00842          else if (insn0length == 48)
00843            {
00844              /* Insert 16 bit coprocessor nop. */
00845              insn.insn = mep_cgen_assemble_insn (gas_cgen_cpu_desc, "cpnop16",
00846                                             &insn.fields, insn.buffer,
00847                                             &errmsg);
00848            }
00849          else
00850            /* Core insn has an invalid length.  Something has gone wrong. */
00851            as_fatal ("Core insn has invalid length!  Something is wrong!");
00852 
00853          if (!insn.insn)
00854            {
00855              as_bad ("%s", errmsg);
00856              return;
00857            }
00858 
00859          /* Now put the insn and fixups into the arrays.  */
00860          mep_save_insn (insn);
00861        }
00862     }
00863 }
00864 
00865 /* The scheduling functions are just filters for invalid combinations.
00866    If there is a violation, they terminate assembly.  Otherise they
00867    just fall through.  Succesful combinations cause no side effects
00868    other than valid nop insertion.  */
00869 
00870 static void
00871 mep_check_parallel_scheduling (void)
00872 {
00873   /* This is where we will eventually read the config information
00874      and choose which scheduling checking function to call.  */   
00875   if (MEP_VLIW64)
00876     mep_check_parallel64_scheduling ();
00877   else
00878     mep_check_parallel32_scheduling ();
00879 }
00880 
00881 static void
00882 mep_process_saved_insns (void)
00883 {
00884   int i;
00885 
00886   gas_cgen_save_fixups (MAX_SAVED_FIXUP_CHAINS - 1);
00887 
00888   /* We have to check for valid scheduling here. */
00889   mep_check_parallel_scheduling ();
00890 
00891   /* If the last call didn't cause assembly to terminate, we have
00892      a valid vliw insn/insn pair saved. Restore this instructions'
00893      fixups and process the insns. */
00894   for (i = 0;i<num_insns_saved;i++)
00895     {
00896       gas_cgen_restore_fixups (i);
00897       gas_cgen_finish_insn (saved_insns[i].insn, saved_insns[i].buffer,
00898                          CGEN_FIELDS_BITSIZE (& saved_insns[i].fields),
00899                          1, NULL);
00900     }
00901   gas_cgen_restore_fixups (MAX_SAVED_FIXUP_CHAINS - 1);
00902 
00903   /* Clear the fixups and reset the number insn saved to 0. */
00904   gas_cgen_initialize_saved_fixups_array ();
00905   num_insns_saved = 0;
00906   listing_prev_line ();
00907 }
00908 
00909 void
00910 md_assemble (char * str)
00911 {
00912   static CGEN_BITSET* isas = NULL;
00913   char * errmsg;
00914 
00915   /* Initialize GAS's cgen interface for a new instruction.  */
00916   gas_cgen_init_parse ();
00917 
00918   /* There are two possible modes: core and vliw.  We have to assemble
00919      differently for each.
00920 
00921      Core Mode:  We assemble normally.  All instructions are on a
00922                  single line and are made up of one mnemonic and one
00923                  set of operands.
00924      VLIW Mode:  Vliw combinations are indicated as follows:
00925 
00926                      core insn
00927                    + copro insn
00928 
00929                  We want to handle the general case where more than
00930                  one instruction can be preceeded by a +.  This will
00931                  happen later if we add support for internally parallel
00932                  coprocessors.  We'll make the parsing nice and general
00933                  so that it can handle an arbitrary number of insns
00934                  with leading +'s.  The actual checking for valid
00935                  combinations is done elsewhere.  */
00936 
00937   /* Initialize the isa to refer to the core.  */
00938   if (isas == NULL)
00939     isas = cgen_bitset_copy (& MEP_CORE_ISA);
00940   else
00941     {
00942       cgen_bitset_clear (isas);
00943       cgen_bitset_union (isas, & MEP_CORE_ISA, isas);
00944     }
00945   gas_cgen_cpu_desc->isas = isas;
00946 
00947   if (mode == VLIW)
00948     {
00949       /* VLIW mode.  */
00950 
00951       int thisInsnIsCopro = 0;
00952       mep_insn insn;
00953       int i;
00954       
00955       /* Initialize the insn buffer */
00956        
00957       if (! CGEN_INT_INSN_P)
00958          for (i=0; i < CGEN_MAX_INSN_SIZE; i++)
00959             insn.buffer[i]='\0';
00960 
00961       /* Can't tell core / copro insns apart at parse time! */
00962       cgen_bitset_union (isas, & MEP_COP_ISA, isas);
00963 
00964       /* Assemble the insn so we can examine its attributes. */
00965       insn.insn = mep_cgen_assemble_insn (gas_cgen_cpu_desc, str,
00966                                      &insn.fields, insn.buffer,
00967                                      &errmsg);
00968       if (!insn.insn)
00969        {
00970          as_bad ("%s", errmsg);
00971          return;
00972        }
00973       mep_check_for_disabled_registers (&insn);
00974 
00975       /* Check to see if it's a coprocessor instruction. */
00976       thisInsnIsCopro = MEP_INSN_COP_P (insn.insn);
00977 
00978       if (!thisInsnIsCopro)
00979        {
00980          insn.insn = mep_cgen_assemble_cop_insn (gas_cgen_cpu_desc, str,
00981                                             &insn.fields, insn.buffer,
00982                                             insn.insn);
00983          thisInsnIsCopro = MEP_INSN_COP_P (insn.insn);
00984          mep_check_for_disabled_registers (&insn);
00985        }
00986 
00987       if (pluspresent)
00988        {
00989          /* A plus was present. */
00990          /* Check for a + with a core insn and abort if found. */
00991          if (!thisInsnIsCopro)
00992            {
00993              as_fatal("A core insn cannot be preceeded by a +.\n");
00994              return;
00995            }
00996 
00997          if (num_insns_saved > 0)
00998            {
00999              /* There are insns in the queue. Add this one. */
01000              mep_save_insn (insn);
01001            }
01002          else
01003            {
01004              /* There are no insns in the queue and a plus is present.
01005                This is a syntax error.  Let's not tolerate this.
01006                We can relax this later if necessary.  */
01007              as_bad (_("Invalid use of parallelization operator."));
01008              return;
01009            }
01010        }
01011       else
01012        {
01013          /* No plus was present. */
01014          if (num_insns_saved > 0)
01015            {
01016              /* There are insns saved and we came across an insn without a
01017                leading +.  That's the signal to process the saved insns
01018                before proceeding then treat the current insn as the first
01019                in a new vliw group.  */
01020              mep_process_saved_insns ();
01021              num_insns_saved = 0;
01022              /* mep_save_insn (insn); */
01023            }
01024          mep_save_insn (insn);
01025 #if 0
01026          else
01027            {
01028 
01029               /* Core Insn. Add it to the beginning of the queue. */
01030               mep_save_insn (insn);
01031              /* gas_cgen_save_fixups(num_insns_saved); */
01032            }
01033 #endif
01034        }
01035 
01036       pluspresent = 0;
01037     }
01038   else
01039     {
01040       /* Core mode.  */
01041 
01042       /* Only single instructions are assembled in core mode. */
01043       mep_insn insn;
01044 
01045       /* If a leading '+' was present, issue an error.
01046         That's not allowed in core mode. */
01047       if (pluspresent)
01048        {
01049          as_bad (_("Leading plus sign not allowed in core mode"));
01050          return;
01051        }
01052 
01053       insn.insn = mep_cgen_assemble_insn
01054        (gas_cgen_cpu_desc, str, & insn.fields, insn.buffer, & errmsg);
01055 
01056       if (!insn.insn)
01057        {
01058          as_bad ("%s", errmsg);
01059          return;
01060        }
01061       gas_cgen_finish_insn (insn.insn, insn.buffer,
01062                          CGEN_FIELDS_BITSIZE (& insn.fields), 1, NULL);
01063       mep_check_for_disabled_registers (&insn);
01064     }
01065 }
01066 
01067 valueT
01068 md_section_align (segT segment, valueT size)
01069 {
01070   int align = bfd_get_section_alignment (stdoutput, segment);
01071   return ((size + (1 << align) - 1) & (-1 << align));
01072 }
01073 
01074 
01075 symbolS *
01076 md_undefined_symbol (char *name ATTRIBUTE_UNUSED)
01077 {
01078   return 0;
01079 }
01080 
01081 /* Interface to relax_segment.  */
01082 
01083 
01084 const relax_typeS md_relax_table[] =
01085 {
01086   /* The fields are:
01087      1) most positive reach of this state,
01088      2) most negative reach of this state,
01089      3) how many bytes this mode will have in the variable part of the frag
01090      4) which index into the table to try if we can't fit into this one.  */
01091   /* Note that we use "beq" because "jmp" has a peculiarity - it cannot
01092      jump to addresses with any bits 27..24 set.  So, we use beq as a
01093      17-bit pc-relative branch to avoid using jmp, just in case.  */
01094 
01095   /* 0 */ {     0,      0, 0, 0 }, /* unused */
01096   /* 1 */ {     0,      0, 0, 0 }, /* marker for "don't know yet" */
01097 
01098   /* 2 */ {  2047,  -2048, 0, 3 }, /* bsr12 */
01099   /* 3 */ {     0,      0, 2, 0 }, /* bsr16 */
01100 
01101   /* 4 */ {  2047,  -2048, 0, 5 }, /* bra */
01102   /* 5 */ { 65535, -65536, 2, 6 }, /* beq $0,$0 */
01103   /* 6 */ {     0,      0, 2, 0 }, /* jmp24 */
01104 
01105   /* 7 */ { 65535, -65536, 0, 8 }, /* beqi */
01106   /* 8 */ {     0,      0, 4, 0 }, /* bnei/jmp */
01107 
01108   /* 9 */  {   127,   -128, 0, 10 }, /* beqz */
01109   /* 10 */ { 65535, -65536, 2, 11 }, /* beqi */
01110   /* 11 */ {     0,      0, 4,  0 }, /* bnei/jmp */
01111 
01112   /* 12 */ { 65535, -65536, 0, 13 }, /* bnei */
01113   /* 13 */ {     0,      0, 4,  0 }, /* beqi/jmp */
01114 
01115   /* 14 */ {   127,   -128, 0, 15 }, /* bnez */
01116   /* 15 */ { 65535, -65536, 2, 16 }, /* bnei */
01117   /* 16 */ {     0,      0, 4,  0 },  /* beqi/jmp */
01118 
01119   /* 17 */ { 65535, -65536, 0, 13 }, /* bgei */
01120   /* 18 */ {     0,      0, 4,  0 },
01121   /* 19 */ { 65535, -65536, 0, 13 }, /* blti */
01122   /* 20 */ {     0,      0, 4,  0 },
01123   /* 19 */ { 65535, -65536, 0, 13 }, /* bcpeq */
01124   /* 20 */ {     0,      0, 4,  0 },
01125   /* 19 */ { 65535, -65536, 0, 13 }, /* bcpne */
01126   /* 20 */ {     0,      0, 4,  0 },
01127   /* 19 */ { 65535, -65536, 0, 13 }, /* bcpat */
01128   /* 20 */ {     0,      0, 4,  0 },
01129   /* 19 */ { 65535, -65536, 0, 13 }, /* bcpaf */
01130   /* 20 */ {     0,      0, 4,  0 }
01131 };
01132 
01133 /* Pseudo-values for 64 bit "insns" which are combinations of two 32
01134    bit insns.  */
01135 typedef enum {
01136   MEP_PSEUDO64_NONE,
01137   MEP_PSEUDO64_16BITCC,
01138   MEP_PSEUDO64_32BITCC,
01139 } MepPseudo64Values;
01140 
01141 static struct {
01142   int insn;
01143   int growth;
01144   int insn_for_extern;
01145 } subtype_mappings[] = {
01146   { 0, 0, 0 },
01147   { 0, 0, 0 },
01148   { MEP_INSN_BSR12, 0, MEP_INSN_BSR24 },
01149   { MEP_INSN_BSR24, 2, MEP_INSN_BSR24 },
01150   { MEP_INSN_BRA,   0, MEP_INSN_BRA   },
01151   { MEP_INSN_BEQ,   2, MEP_INSN_BEQ   },
01152   { MEP_INSN_JMP,   2, MEP_INSN_JMP   },
01153   { MEP_INSN_BEQI,  0, MEP_INSN_BEQI  },
01154   { -1,             4, MEP_PSEUDO64_32BITCC },
01155   { MEP_INSN_BEQZ,  0, MEP_INSN_BEQZ  },
01156   { MEP_INSN_BEQI,  2, MEP_INSN_BEQI  },
01157   { -1,             4, MEP_PSEUDO64_16BITCC },
01158   { MEP_INSN_BNEI,  0, MEP_INSN_BNEI  },
01159   { -1,             4, MEP_PSEUDO64_32BITCC },
01160   { MEP_INSN_BNEZ,  0, MEP_INSN_BNEZ  },
01161   { MEP_INSN_BNEI,  2, MEP_INSN_BNEI  },
01162   { -1,             4, MEP_PSEUDO64_16BITCC },
01163   { MEP_INSN_BGEI,  0, MEP_INSN_BGEI  },
01164   { -1,             4, MEP_PSEUDO64_32BITCC },
01165   { MEP_INSN_BLTI,  0, MEP_INSN_BLTI  },
01166   { -1,             4, MEP_PSEUDO64_32BITCC },
01167   { MEP_INSN_BCPEQ, 0, MEP_INSN_BCPEQ  },
01168   { -1,             4, MEP_PSEUDO64_32BITCC },
01169   { MEP_INSN_BCPNE, 0, MEP_INSN_BCPNE  },
01170   { -1,             4, MEP_PSEUDO64_32BITCC },
01171   { MEP_INSN_BCPAT, 0, MEP_INSN_BCPAT  },
01172   { -1,             4, MEP_PSEUDO64_32BITCC },
01173   { MEP_INSN_BCPAF, 0, MEP_INSN_BCPAF  },
01174   { -1,             4, MEP_PSEUDO64_32BITCC }
01175 };
01176 #define NUM_MAPPINGS (sizeof (subtype_mappings) / sizeof (subtype_mappings[0]))
01177 
01178 void
01179 mep_prepare_relax_scan (fragS *fragP, offsetT *aim, relax_substateT this_state)
01180 {
01181   symbolS *symbolP = fragP->fr_symbol;
01182   if (symbolP && !S_IS_DEFINED (symbolP))
01183     *aim = 0;
01184   /* Adjust for MeP pcrel not being relative to the next opcode.  */
01185   *aim += 2 + md_relax_table[this_state].rlx_length;
01186 }
01187 
01188 static int
01189 insn_to_subtype (int insn)
01190 {
01191   unsigned int i;
01192   for (i=0; i<NUM_MAPPINGS; i++)
01193     if (insn == subtype_mappings[i].insn)
01194       return i;
01195   abort ();
01196 }
01197 
01198 /* Return an initial guess of the length by which a fragment must grow
01199    to hold a branch to reach its destination.  Also updates fr_type
01200    and fr_subtype as necessary.
01201 
01202    Called just before doing relaxation.  Any symbol that is now
01203    undefined will not become defined.  The guess for fr_var is
01204    ACTUALLY the growth beyond fr_fix.  Whatever we do to grow fr_fix
01205    or fr_var contributes to our returned value.  Although it may not
01206    be explicit in the frag, pretend fr_var starts with a 0 value.  */
01207 
01208 int
01209 md_estimate_size_before_relax (fragS * fragP, segT segment)
01210 {
01211   if (fragP->fr_subtype == 1)
01212     fragP->fr_subtype = insn_to_subtype (fragP->fr_cgen.insn->base->num);
01213 
01214   if (S_GET_SEGMENT (fragP->fr_symbol) != segment)
01215     {
01216       int new_insn;
01217 
01218       new_insn = subtype_mappings[fragP->fr_subtype].insn_for_extern;
01219       fragP->fr_subtype = insn_to_subtype (new_insn);
01220     }
01221 
01222   if (MEP_VLIW && ! MEP_VLIW64
01223       && (bfd_get_section_flags (stdoutput, segment) & SEC_MEP_VLIW))
01224     {
01225       /* Use 32 bit branches for vliw32 so the vliw word is not split.  */
01226       switch (fragP->fr_cgen.insn->base->num)
01227        {
01228        case MEP_INSN_BSR12:
01229          fragP->fr_subtype = insn_to_subtype 
01230            (subtype_mappings[fragP->fr_subtype].insn_for_extern);
01231          break;
01232        case MEP_INSN_BEQZ:
01233          fragP->fr_subtype ++;
01234          break;
01235        case MEP_INSN_BNEZ:
01236          fragP->fr_subtype ++;
01237          break;
01238        }
01239     }
01240 
01241   if (fragP->fr_cgen.insn->base
01242       && fragP->fr_cgen.insn->base->num
01243          != subtype_mappings[fragP->fr_subtype].insn)
01244     {
01245       int new_insn= subtype_mappings[fragP->fr_subtype].insn;
01246       if (new_insn != -1)
01247        {
01248          fragP->fr_cgen.insn = (fragP->fr_cgen.insn
01249                              - fragP->fr_cgen.insn->base->num
01250                              + new_insn);
01251        }
01252     }
01253 
01254   return subtype_mappings[fragP->fr_subtype].growth;
01255 }
01256 
01257 /* *fragP has been relaxed to its final size, and now needs to have
01258    the bytes inside it modified to conform to the new size.
01259 
01260    Called after relaxation is finished.
01261    fragP->fr_type == rs_machine_dependent.
01262    fragP->fr_subtype is the subtype of what the address relaxed to.  */
01263 
01264 static int
01265 target_address_for (fragS *frag)
01266 {
01267   int rv = frag->fr_offset;
01268   symbolS *sym = frag->fr_symbol;
01269 
01270   if (sym)
01271     rv += S_GET_VALUE (sym);
01272 
01273   return rv;
01274 }
01275 
01276 void
01277 md_convert_frag (bfd *abfd  ATTRIBUTE_UNUSED, 
01278                segT sec ATTRIBUTE_UNUSED,
01279                fragS *fragP)
01280 {
01281   int addend, rn, bit = 0;
01282   int operand;
01283   int where = fragP->fr_opcode - fragP->fr_literal;
01284   int e = target_big_endian ? 0 : 1;
01285 
01286   addend = target_address_for (fragP) - (fragP->fr_address + where);
01287 
01288   if (subtype_mappings[fragP->fr_subtype].insn == -1)
01289     {
01290       fragP->fr_fix += subtype_mappings[fragP->fr_subtype].growth;
01291       switch (subtype_mappings[fragP->fr_subtype].insn_for_extern)
01292        {
01293        case MEP_PSEUDO64_16BITCC:
01294          fragP->fr_opcode[1^e] = ((fragP->fr_opcode[1^e] & 1) ^ 1) | 0x06;
01295          fragP->fr_opcode[2^e] = 0xd8;
01296          fragP->fr_opcode[3^e] = 0x08;
01297          fragP->fr_opcode[4^e] = 0;
01298          fragP->fr_opcode[5^e] = 0;
01299          where += 2;
01300          break;
01301        case MEP_PSEUDO64_32BITCC:
01302          if (fragP->fr_opcode[0^e] & 0x10)
01303            fragP->fr_opcode[1^e] ^= 0x01;
01304          else
01305            fragP->fr_opcode[1^e] ^= 0x04;
01306          fragP->fr_opcode[2^e] = 0;
01307          fragP->fr_opcode[3^e] = 4;
01308          fragP->fr_opcode[4^e] = 0xd8;
01309          fragP->fr_opcode[5^e] = 0x08;
01310          fragP->fr_opcode[6^e] = 0;
01311          fragP->fr_opcode[7^e] = 0;
01312          where += 4;
01313          break;
01314        default:
01315          abort ();
01316        }
01317       fragP->fr_cgen.insn = (fragP->fr_cgen.insn
01318                           - fragP->fr_cgen.insn->base->num
01319                           + MEP_INSN_JMP);
01320       operand = MEP_OPERAND_PCABS24A2;
01321     }
01322   else
01323     switch (fragP->fr_cgen.insn->base->num)
01324       {
01325       case MEP_INSN_BSR12:
01326        fragP->fr_opcode[0^e] = 0xb0 | ((addend >> 8) & 0x0f);
01327        fragP->fr_opcode[1^e] = 0x01 | (addend & 0xfe);
01328        operand = MEP_OPERAND_PCREL12A2;
01329        break;
01330 
01331       case MEP_INSN_BSR24:
01332        fragP->fr_fix += 2;
01333        fragP->fr_opcode[0^e] = 0xd8 | ((addend >> 5) & 0x07);
01334        fragP->fr_opcode[1^e] = 0x09 | ((addend << 3) & 0xf0);
01335        fragP->fr_opcode[2^e] = 0x00 | ((addend >>16) & 0xff);
01336        fragP->fr_opcode[3^e] = 0x00 | ((addend >> 8) & 0xff);
01337        operand = MEP_OPERAND_PCREL24A2;
01338        break;
01339 
01340       case MEP_INSN_BRA:
01341        fragP->fr_opcode[0^e] = 0xb0 | ((addend >> 8) & 0x0f);
01342        fragP->fr_opcode[1^e] = 0x00 | (addend & 0xfe);
01343        operand = MEP_OPERAND_PCREL12A2;
01344        break;
01345 
01346       case MEP_INSN_BEQ:
01347        /* The default relax_frag doesn't change the state if there is no
01348           growth, so we must manually handle converting out-of-range BEQ
01349           instructions to JMP.  */
01350        if (addend <= 65535 && addend >= -65536)
01351          {
01352            fragP->fr_fix += 2;
01353            fragP->fr_opcode[0^e] = 0xe0;
01354            fragP->fr_opcode[1^e] = 0x01;
01355            fragP->fr_opcode[2^e] = 0x00 | ((addend >> 9) & 0xff);
01356            fragP->fr_opcode[3^e] = 0x00 | ((addend >> 1) & 0xff);
01357            operand = MEP_OPERAND_PCREL17A2;
01358            break;
01359          }
01360        /* ...FALLTHROUGH... */
01361 
01362       case MEP_INSN_JMP:
01363        addend = target_address_for (fragP);
01364        fragP->fr_fix += 2;
01365        fragP->fr_opcode[0^e] = 0xd8 | ((addend >> 5) & 0x07);
01366        fragP->fr_opcode[1^e] = 0x08 | ((addend << 3) & 0xf0);
01367        fragP->fr_opcode[2^e] = 0x00 | ((addend >>16) & 0xff);
01368        fragP->fr_opcode[3^e] = 0x00 | ((addend >> 8) & 0xff);
01369        operand = MEP_OPERAND_PCABS24A2;
01370        break;
01371 
01372       case MEP_INSN_BNEZ:
01373        bit = 1;
01374       case MEP_INSN_BEQZ:
01375        fragP->fr_opcode[1^e] = bit | (addend & 0xfe);
01376        operand = MEP_OPERAND_PCREL8A2;
01377        break;
01378 
01379       case MEP_INSN_BNEI:
01380        bit = 4;
01381       case MEP_INSN_BEQI:
01382        if (subtype_mappings[fragP->fr_subtype].growth)
01383          {
01384            fragP->fr_fix += subtype_mappings[fragP->fr_subtype].growth;
01385            rn = fragP->fr_opcode[0^e] & 0x0f;
01386            fragP->fr_opcode[0^e] = 0xe0 | rn;
01387            fragP->fr_opcode[1^e] = bit;
01388          }
01389        fragP->fr_opcode[2^e] = 0x00 | ((addend >> 9) & 0xff);
01390        fragP->fr_opcode[3^e] = 0x00 | ((addend >> 1) & 0xff);
01391        operand = MEP_OPERAND_PCREL17A2;
01392        break;
01393 
01394       case MEP_INSN_BLTI:
01395       case MEP_INSN_BGEI:
01396       case MEP_INSN_BCPEQ:
01397       case MEP_INSN_BCPNE:
01398       case MEP_INSN_BCPAT:
01399       case MEP_INSN_BCPAF:
01400        /* No opcode change needed, just operand.  */
01401        fragP->fr_opcode[2^e] = (addend >> 9) & 0xff;
01402        fragP->fr_opcode[3^e] = (addend >> 1) & 0xff;
01403        operand = MEP_OPERAND_PCREL17A2;
01404        break;
01405 
01406       default:
01407        abort ();
01408       }
01409 
01410   if (S_GET_SEGMENT (fragP->fr_symbol) != sec
01411       || operand == MEP_OPERAND_PCABS24A2)
01412     {
01413       assert (fragP->fr_cgen.insn != 0);
01414       gas_cgen_record_fixup (fragP,
01415                           where,
01416                           fragP->fr_cgen.insn,
01417                           (fragP->fr_fix - where) * 8,
01418                           cgen_operand_lookup_by_num (gas_cgen_cpu_desc,
01419                                                   operand),
01420                           fragP->fr_cgen.opinfo,
01421                           fragP->fr_symbol, fragP->fr_offset);
01422     }
01423 }
01424 
01425 
01426 /* Functions concerning relocs.  */
01427 
01428 void
01429 mep_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
01430 {
01431   /* If we already know the fixup value, adjust it in the same
01432      way that the linker would have done.  */
01433   if (fixP->fx_addsy == 0)
01434     switch (fixP->fx_cgen.opinfo)
01435       {
01436       case BFD_RELOC_MEP_LOW16:
01437        *valP = ((long)(*valP & 0xffff)) << 16 >> 16;
01438        break;
01439       case BFD_RELOC_MEP_HI16U:
01440        *valP >>= 16;
01441        break;
01442       case BFD_RELOC_MEP_HI16S:
01443        *valP = (*valP + 0x8000) >> 16;
01444        break;
01445       }
01446 
01447   /* Now call cgen's md_aply_fix.  */
01448   gas_cgen_md_apply_fix (fixP, valP, seg);
01449 }
01450 
01451 long
01452 md_pcrel_from_section (fixS *fixP, segT sec)
01453 {
01454   if (fixP->fx_addsy != (symbolS *) NULL
01455       && (! S_IS_DEFINED (fixP->fx_addsy)
01456          || S_GET_SEGMENT (fixP->fx_addsy) != sec))
01457     /* The symbol is undefined (or is defined but not in this section).
01458        Let the linker figure it out.  */
01459     return 0;
01460 
01461   /* Return the address of the opcode - cgen adjusts for opcode size
01462      itself, to be consistent with the disassembler, which must do
01463      so.  */
01464   return fixP->fx_where + fixP->fx_frag->fr_address;
01465 }
01466 
01467 /* Return the bfd reloc type for OPERAND of INSN at fixup FIXP.
01468    Returns BFD_RELOC_NONE if no reloc type can be found.
01469    *FIXP may be modified if desired.  */
01470 
01471 #if defined (__STDC__) || defined (ALMOST_STDC) || defined (HAVE_STRINGIZE)
01472 #define MAP(n) case MEP_OPERAND_##n: return BFD_RELOC_MEP_##n;
01473 #else
01474 #define MAP(n) case MEP_OPERAND_n: return BFD_RELOC_MEP_n;
01475 #endif
01476 
01477 bfd_reloc_code_real_type
01478 md_cgen_lookup_reloc (const CGEN_INSN *insn ATTRIBUTE_UNUSED,
01479                     const CGEN_OPERAND *operand,
01480                     fixS *fixP)
01481 {
01482   enum bfd_reloc_code_real reloc = fixP->fx_cgen.opinfo;
01483   static char printed[MEP_OPERAND_MAX] = { 0 };
01484 
01485   /* If there's a reloc here, it's because the parser saw a %foo() and
01486      is giving us the correct reloc to use, or because we converted to
01487      a different size reloc below and want to avoid "converting" more
01488      than once.  */
01489   if (reloc && reloc != BFD_RELOC_NONE)
01490     return reloc;
01491 
01492   switch (operand->type)
01493     {
01494       MAP (PCREL8A2);       /* beqz */
01495       MAP (PCREL12A2);      /* bsr16 */
01496       MAP (PCREL17A2);      /* beqi */
01497       MAP (PCREL24A2);      /* bsr24 */
01498       MAP (PCABS24A2);      /* jmp */
01499       MAP (UIMM24);  /* mov */
01500       MAP (ADDR24A4);       /* sw/lw */
01501 
01502     /* The rest of the relocs should be generated by the parser,
01503        for things such as %tprel(), etc. */
01504     case MEP_OPERAND_SIMM16:
01505 #ifdef OBJ_COMPLEX_RELC
01506       /* coalescing this into RELOC_MEP_16 is actually a bug,
01507         since it's a signed operand. let the relc code handle it. */
01508       return BFD_RELOC_RELC; 
01509 #endif
01510 
01511     case MEP_OPERAND_UIMM16:
01512     case MEP_OPERAND_SDISP16:
01513     case MEP_OPERAND_CODE16:
01514       fixP->fx_where += 2;
01515       /* to avoid doing the above add twice */
01516       fixP->fx_cgen.opinfo = BFD_RELOC_MEP_16;
01517       return BFD_RELOC_MEP_16;
01518 
01519     default:
01520 #ifdef OBJ_COMPLEX_RELC
01521       /* this is not an error, yet. 
01522         pass it to the linker. */
01523       return BFD_RELOC_RELC;
01524 #endif
01525       if (printed[operand->type])
01526        return BFD_RELOC_NONE;
01527       printed[operand->type] = 1;
01528 
01529       as_bad_where (fixP->fx_file, fixP->fx_line,
01530                   _("Don't know how to relocate plain operands of type %s"),
01531                   operand->name);
01532 
01533       /* Print some helpful hints for the user.  */
01534       switch (operand->type)
01535        {
01536        case MEP_OPERAND_UDISP7:
01537        case MEP_OPERAND_UDISP7A2:
01538        case MEP_OPERAND_UDISP7A4:
01539          as_bad_where (fixP->fx_file, fixP->fx_line,
01540                      _("Perhaps you are missing %%tpoff()?"));
01541          break;
01542        default:
01543          break;
01544        }
01545       return BFD_RELOC_NONE;
01546     }
01547 }
01548 
01549 /* Called while parsing an instruction to create a fixup.
01550    We need to check for HI16 relocs and queue them up for later sorting.  */
01551 
01552 fixS *
01553 mep_cgen_record_fixup_exp (fragS *frag,
01554                         int where,
01555                         const CGEN_INSN *insn,
01556                         int length,
01557                         const CGEN_OPERAND *operand,
01558                         int opinfo,
01559                         expressionS *exp)
01560 {
01561   fixS * fixP = gas_cgen_record_fixup_exp (frag, where, insn, length,
01562                                       operand, opinfo, exp);
01563   return fixP;
01564 }
01565 
01566 /* Return BFD reloc type from opinfo field in a fixS.
01567    It's tricky using fx_r_type in mep_frob_file because the values
01568    are BFD_RELOC_UNUSED + operand number.  */
01569 #define FX_OPINFO_R_TYPE(f) ((f)->fx_cgen.opinfo)
01570 
01571 /* Sort any unmatched HI16 relocs so that they immediately precede
01572    the corresponding LO16 reloc.  This is called before md_apply_fix and
01573    tc_gen_reloc.  */
01574 
01575 void
01576 mep_frob_file ()
01577 {
01578   struct mep_hi_fixup * l;
01579 
01580   for (l = mep_hi_fixup_list; l != NULL; l = l->next)
01581     {
01582       segment_info_type * seginfo;
01583       int pass;
01584 
01585       assert (FX_OPINFO_R_TYPE (l->fixp) == BFD_RELOC_HI16
01586              || FX_OPINFO_R_TYPE (l->fixp) == BFD_RELOC_LO16);
01587 
01588       /* Check quickly whether the next fixup happens to be a matching low.  */
01589       if (l->fixp->fx_next != NULL
01590          && FX_OPINFO_R_TYPE (l->fixp->fx_next) == BFD_RELOC_LO16
01591          && l->fixp->fx_addsy == l->fixp->fx_next->fx_addsy
01592          && l->fixp->fx_offset == l->fixp->fx_next->fx_offset)
01593        continue;
01594 
01595       /* Look through the fixups for this segment for a matching
01596          `low'.  When we find one, move the high just in front of it.
01597          We do this in two passes.  In the first pass, we try to find
01598          a unique `low'.  In the second pass, we permit multiple
01599          high's relocs for a single `low'.  */
01600       seginfo = seg_info (l->seg);
01601       for (pass = 0; pass < 2; pass++)
01602        {
01603          fixS * f;
01604          fixS * prev;
01605 
01606          prev = NULL;
01607          for (f = seginfo->fix_root; f != NULL; f = f->fx_next)
01608            {
01609              /* Check whether this is a `low' fixup which matches l->fixp.  */
01610              if (FX_OPINFO_R_TYPE (f) == BFD_RELOC_LO16
01611                 && f->fx_addsy == l->fixp->fx_addsy
01612                 && f->fx_offset == l->fixp->fx_offset
01613                 && (pass == 1
01614                     || prev == NULL
01615                     || (FX_OPINFO_R_TYPE (prev) != BFD_RELOC_HI16)
01616                     || prev->fx_addsy != f->fx_addsy
01617                     || prev->fx_offset !=  f->fx_offset))
01618               {
01619                 fixS ** pf;
01620 
01621                 /* Move l->fixp before f.  */
01622                 for (pf = &seginfo->fix_root;
01623                      * pf != l->fixp;
01624                      pf = & (* pf)->fx_next)
01625                   assert (* pf != NULL);
01626 
01627                 * pf = l->fixp->fx_next;
01628 
01629                 l->fixp->fx_next = f;
01630                 if (prev == NULL)
01631                   seginfo->fix_root = l->fixp;
01632                 else
01633                   prev->fx_next = l->fixp;
01634 
01635                 break;
01636               }
01637 
01638              prev = f;
01639            }
01640 
01641          if (f != NULL)
01642            break;
01643 
01644          if (pass == 1)
01645            as_warn_where (l->fixp->fx_file, l->fixp->fx_line,
01646                         _("Unmatched high relocation"));
01647        }
01648     }
01649 }
01650 
01651 /* See whether we need to force a relocation into the output file. */
01652 
01653 int
01654 mep_force_relocation (fixS *fixp)
01655 {
01656   if (   fixp->fx_r_type == BFD_RELOC_VTABLE_INHERIT
01657         || fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
01658     return 1;
01659 
01660   /* Allow branches to global symbols to be resolved at assembly time.
01661      This is consistent with way relaxable branches are handled, since
01662      branches to both global and local symbols are relaxed.  It also
01663      corresponds to the assumptions made in md_pcrel_from_section.  */
01664   return S_FORCE_RELOC (fixp->fx_addsy, !fixp->fx_pcrel);
01665 }
01666 
01667 /* Write a value out to the object file, using the appropriate endianness.  */
01668 
01669 void
01670 md_number_to_chars (char *buf, valueT val, int n)
01671 {
01672   if (target_big_endian)
01673     number_to_chars_bigendian (buf, val, n);
01674   else
01675     number_to_chars_littleendian (buf, val, n);
01676 }
01677 
01678 /* Turn a string in input_line_pointer into a floating point constant
01679    of type type, and store the appropriate bytes in *litP.  The number
01680    of LITTLENUMS emitted is stored in *sizeP .  An error message is
01681    returned, or NULL on OK. */
01682 
01683 /* Equal to MAX_PRECISION in atof-ieee.c */
01684 #define MAX_LITTLENUMS 6
01685 
01686 char *
01687 md_atof (int type, char *litP, int *sizeP)
01688 {
01689   int              i;
01690   int              prec;
01691   LITTLENUM_TYPE   words [MAX_LITTLENUMS];
01692   char *           t;
01693 
01694   switch (type)
01695     {
01696     case 'f':
01697     case 'F':
01698     case 's':
01699     case 'S':
01700       prec = 2;
01701       break;
01702 
01703     case 'd':
01704     case 'D':
01705     case 'r':
01706     case 'R':
01707       prec = 4;
01708       break;
01709 
01710     /* FIXME: Some targets allow other format chars for bigger sizes here.  */
01711     default:
01712       *sizeP = 0;
01713       return _("Bad call to md_atof()");
01714     }
01715 
01716   t = atof_ieee (input_line_pointer, type, words);
01717   if (t)
01718     input_line_pointer = t;
01719   * sizeP = prec * sizeof (LITTLENUM_TYPE);
01720 
01721   for (i = 0; i < prec; i++)
01722     {
01723       md_number_to_chars (litP, (valueT) words[i],
01724                        sizeof (LITTLENUM_TYPE));
01725       litP += sizeof (LITTLENUM_TYPE);
01726     }
01727 
01728   return 0;
01729 }
01730 
01731 
01732 bfd_boolean
01733 mep_fix_adjustable (fixS *fixP)
01734 {
01735   bfd_reloc_code_real_type reloc_type;
01736 
01737   if ((int) fixP->fx_r_type >= (int) BFD_RELOC_UNUSED)
01738     {
01739       const CGEN_INSN *insn = NULL;
01740       int opindex = (int) fixP->fx_r_type - (int) BFD_RELOC_UNUSED;
01741       const CGEN_OPERAND *operand
01742        = cgen_operand_lookup_by_num(gas_cgen_cpu_desc, opindex);
01743       reloc_type = md_cgen_lookup_reloc (insn, operand, fixP);
01744     }
01745   else
01746     reloc_type = fixP->fx_r_type;
01747 
01748   if (fixP->fx_addsy == NULL)
01749     return 1;
01750 
01751   /* Prevent all adjustments to global symbols. */
01752   if (S_IS_EXTERNAL (fixP->fx_addsy))
01753     return 0;
01754 
01755   if (S_IS_WEAK (fixP->fx_addsy))
01756     return 0;
01757 
01758   /* We need the symbol name for the VTABLE entries */
01759   if (reloc_type == BFD_RELOC_VTABLE_INHERIT
01760       || reloc_type == BFD_RELOC_VTABLE_ENTRY)
01761     return 0;
01762 
01763   return 1;
01764 }
01765 
01766 int
01767 mep_elf_section_letter (int letter, char **ptrmsg)
01768 {
01769   if (letter == 'v')
01770     return SHF_MEP_VLIW;
01771 
01772   *ptrmsg = _("Bad .section directive: want a,v,w,x,M,S in string");
01773   return 0;
01774 }
01775 
01776 flagword
01777 mep_elf_section_flags (flagword flags, int attr, int type ATTRIBUTE_UNUSED)
01778 {
01779   if (attr & SHF_MEP_VLIW)
01780     flags |= SEC_MEP_VLIW;
01781   return flags;
01782 }
01783 
01784 /* In vliw mode, the default section is .vtext.  We have to be able
01785    to switch into .vtext using only the .vtext directive.  */
01786 
01787 static segT
01788 mep_vtext_section (void)
01789 {
01790   static segT vtext_section;
01791 
01792   if (! vtext_section)
01793     {
01794       flagword applicable = bfd_applicable_section_flags (stdoutput);
01795       vtext_section = subseg_new (VTEXT_SECTION_NAME, 0);
01796       bfd_set_section_flags (stdoutput, vtext_section,
01797                           applicable & (SEC_ALLOC | SEC_LOAD | SEC_RELOC
01798                                       | SEC_CODE | SEC_READONLY
01799                                       | SEC_MEP_VLIW));
01800     }
01801 
01802   return vtext_section;
01803 }
01804 
01805 static void
01806 mep_s_vtext (int ignore ATTRIBUTE_UNUSED)
01807 {
01808   int temp;
01809 
01810   /* Record previous_section and previous_subsection.  */
01811   obj_elf_section_change_hook ();
01812 
01813   temp = get_absolute_expression ();
01814   subseg_set (mep_vtext_section (), (subsegT) temp);
01815   demand_empty_rest_of_line ();
01816 }
01817 
01818 static void
01819 mep_switch_to_core_mode (int dummy ATTRIBUTE_UNUSED)
01820 {
01821   mep_process_saved_insns ();
01822   pluspresent = 0;
01823   mode = CORE;
01824 }
01825 
01826 static void
01827 mep_switch_to_vliw_mode (int dummy ATTRIBUTE_UNUSED)
01828 {
01829   if (! MEP_VLIW)
01830     as_bad (_(".vliw unavailable when VLIW is disabled."));
01831   mode = VLIW;
01832   /* Switch into .vtext here too. */
01833   /* mep_s_vtext(); */
01834 }
01835 
01836 /* This is an undocumented pseudo-op used to disable gas's
01837    "disabled_registers" check.  Used for code which checks for those
01838    registers at runtime.  */
01839 static void
01840 mep_noregerr (int i ATTRIBUTE_UNUSED)
01841 {
01842   allow_disabled_registers = 1;
01843 }
01844 
01845 /* mep_unrecognized_line: This is called when a line that can't be parsed
01846    is encountered.  We use it to check for a leading '+' sign which indicates
01847    that the current instruction is a coprocessor instruction that is to be
01848    parallelized with a previous core insn.  This function accepts the '+' and
01849    rejects all other characters that might indicate garbage at the beginning
01850    of the line.  The '+' character gets lost as the calling loop continues,
01851    so we need to indicate that we saw it.  */
01852 
01853 int
01854 mep_unrecognized_line (int ch)
01855 {
01856   switch (ch)
01857     {
01858     case '+':
01859       pluspresent = 1;
01860       return 1; /* '+' indicates an instruction to be parallelized. */
01861     default:
01862       return 0; /* If it's not a '+', the line can't be parsed. */
01863     }
01864 }
01865 
01866 void
01867 mep_cleanup (void)
01868 {
01869   /* Take care of any insns left to be parallelized when the file ends.
01870      This is mainly here to handle the case where the file ends with an
01871      insn preceeded by a + or the file ends unexpectedly.  */
01872   if (mode == VLIW)
01873     mep_process_saved_insns ();
01874 }
01875 
01876 int
01877 mep_flush_pending_output (void)
01878 {
01879   if (mode == VLIW)
01880     {
01881       mep_process_saved_insns ();
01882       pluspresent = 0;
01883     }
01884 
01885   return 1; 
01886 }