]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - contrib/binutils/gas/config/tc-mep.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / contrib / binutils / gas / config / tc-mep.c
1 /* tc-mep.c -- Assembler for the Toshiba Media Processor.
2    Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation.
3
4    This file is part of GAS, the GNU Assembler.
5
6    GAS is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 2, or (at your option)
9    any later version.
10
11    GAS is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with GAS; see the file COPYING.  If not, write to
18    the Free Software Foundation, 51 Franklin Street, Fifth Floor,
19    Boston, MA 02110-1301, USA.  */
20
21 #include <stdio.h>
22 #include "as.h"
23 #include "dwarf2dbg.h"
24 #include "subsegs.h"
25 #include "symcat.h"
26 #include "opcodes/mep-desc.h"
27 #include "opcodes/mep-opc.h"
28 #include "cgen.h"
29 #include "elf/common.h"
30 #include "elf/mep.h"
31 #include "libbfd.h"
32 #include "xregex.h"
33
34 /* Structure to hold all of the different components describing
35    an individual instruction.  */
36 typedef struct
37 {
38   const CGEN_INSN *     insn;
39   const CGEN_INSN *     orig_insn;
40   CGEN_FIELDS           fields;
41 #if CGEN_INT_INSN_P
42   CGEN_INSN_INT         buffer [1];
43 #define INSN_VALUE(buf) (*(buf))
44 #else
45   unsigned char         buffer [CGEN_MAX_INSN_SIZE];
46 #define INSN_VALUE(buf) (buf)
47 #endif
48   char *                addr;
49   fragS *               frag;
50   int                   num_fixups;
51   fixS *                fixups [GAS_CGEN_MAX_FIXUPS];
52   int                   indices [MAX_OPERAND_INSTANCES];
53 } mep_insn;
54
55 static int mode = CORE; /* Start in core mode. */
56 static int pluspresent = 0;
57 static int allow_disabled_registers = 0;
58 static int library_flag = 0;
59
60 /* We're going to need to store all of the instructions along with
61    their fixups so that we can parallelization grouping rules. */
62
63 static mep_insn saved_insns[MAX_SAVED_FIXUP_CHAINS];
64 static int num_insns_saved = 0;
65
66 const char comment_chars[]        = "#";
67 const char line_comment_chars[]   = ";#";
68 const char line_separator_chars[] = ";";
69 const char EXP_CHARS[]            = "eE";
70 const char FLT_CHARS[]            = "dD";
71
72 static void mep_switch_to_vliw_mode (int);
73 static void mep_switch_to_core_mode (int);
74 static void mep_s_vtext (int);
75 static void mep_noregerr (int);
76
77 /* The target specific pseudo-ops which we support.  */
78 const pseudo_typeS md_pseudo_table[] =
79 {
80   { "word",     cons,                           4 },
81   { "file",     (void (*) (int)) dwarf2_directive_file,         0 },
82   { "loc",      dwarf2_directive_loc,           0 },
83   { "vliw",     mep_switch_to_vliw_mode,        0 },
84   { "core",     mep_switch_to_core_mode,        0 },
85   { "vtext",    mep_s_vtext,                    0 },
86   { "noregerr", mep_noregerr,                   0 },
87   { NULL,       NULL,                           0 }
88 };
89
90 /* Relocations against symbols are done in two
91    parts, with a HI relocation and a LO relocation.  Each relocation
92    has only 16 bits of space to store an addend.  This means that in
93    order for the linker to handle carries correctly, it must be able
94    to locate both the HI and the LO relocation.  This means that the
95    relocations must appear in order in the relocation table.
96
97    In order to implement this, we keep track of each unmatched HI
98    relocation.  We then sort them so that they immediately precede the
99    corresponding LO relocation. */
100
101 struct mep_hi_fixup
102 {
103   struct mep_hi_fixup * next;   /* Next HI fixup.  */
104   fixS * fixp;                  /* This fixup.  */
105   segT seg;                     /* The section this fixup is in.  */
106 };
107
108 /* The list of unmatched HI relocs.  */
109 static struct mep_hi_fixup * mep_hi_fixup_list;
110
111 \f
112 #define OPTION_EB               (OPTION_MD_BASE + 0)
113 #define OPTION_EL               (OPTION_MD_BASE + 1)
114 #define OPTION_CONFIG           (OPTION_MD_BASE + 2)
115 #define OPTION_AVERAGE          (OPTION_MD_BASE + 3)
116 #define OPTION_NOAVERAGE        (OPTION_MD_BASE + 4)
117 #define OPTION_MULT             (OPTION_MD_BASE + 5)
118 #define OPTION_NOMULT           (OPTION_MD_BASE + 6)
119 #define OPTION_DIV              (OPTION_MD_BASE + 7)
120 #define OPTION_NODIV            (OPTION_MD_BASE + 8)
121 #define OPTION_BITOPS           (OPTION_MD_BASE + 9)
122 #define OPTION_NOBITOPS         (OPTION_MD_BASE + 10)
123 #define OPTION_LEADZ            (OPTION_MD_BASE + 11)
124 #define OPTION_NOLEADZ          (OPTION_MD_BASE + 12)
125 #define OPTION_ABSDIFF          (OPTION_MD_BASE + 13)
126 #define OPTION_NOABSDIFF        (OPTION_MD_BASE + 14)
127 #define OPTION_MINMAX           (OPTION_MD_BASE + 15)
128 #define OPTION_NOMINMAX         (OPTION_MD_BASE + 16)
129 #define OPTION_CLIP             (OPTION_MD_BASE + 17)
130 #define OPTION_NOCLIP           (OPTION_MD_BASE + 18)
131 #define OPTION_SATUR            (OPTION_MD_BASE + 19)
132 #define OPTION_NOSATUR          (OPTION_MD_BASE + 20)
133 #define OPTION_COP32            (OPTION_MD_BASE + 21)
134 #define OPTION_REPEAT           (OPTION_MD_BASE + 25)
135 #define OPTION_NOREPEAT         (OPTION_MD_BASE + 26)
136 #define OPTION_DEBUG            (OPTION_MD_BASE + 27)
137 #define OPTION_NODEBUG          (OPTION_MD_BASE + 28)
138 #define OPTION_LIBRARY          (OPTION_MD_BASE + 29)
139
140 struct option md_longopts[] = {
141   { "EB",          no_argument, NULL, OPTION_EB},
142   { "EL",          no_argument, NULL, OPTION_EL},
143   { "mconfig",     required_argument, NULL, OPTION_CONFIG},
144   { "maverage",    no_argument, NULL, OPTION_AVERAGE},
145   { "mno-average", no_argument, NULL, OPTION_NOAVERAGE},
146   { "mmult",       no_argument, NULL, OPTION_MULT},
147   { "mno-mult",    no_argument, NULL, OPTION_NOMULT},
148   { "mdiv",        no_argument, NULL, OPTION_DIV},
149   { "mno-div",     no_argument, NULL, OPTION_NODIV},
150   { "mbitops",     no_argument, NULL, OPTION_BITOPS},
151   { "mno-bitops",  no_argument, NULL, OPTION_NOBITOPS},
152   { "mleadz",      no_argument, NULL, OPTION_LEADZ},
153   { "mno-leadz",   no_argument, NULL, OPTION_NOLEADZ},
154   { "mabsdiff",    no_argument, NULL, OPTION_ABSDIFF},
155   { "mno-absdiff", no_argument, NULL, OPTION_NOABSDIFF},
156   { "mminmax",     no_argument, NULL, OPTION_MINMAX},
157   { "mno-minmax",  no_argument, NULL, OPTION_NOMINMAX},
158   { "mclip",       no_argument, NULL, OPTION_CLIP},
159   { "mno-clip",    no_argument, NULL, OPTION_NOCLIP},
160   { "msatur",      no_argument, NULL, OPTION_SATUR},
161   { "mno-satur",   no_argument, NULL, OPTION_NOSATUR},
162   { "mcop32",      no_argument, NULL, OPTION_COP32},
163   { "mdebug",      no_argument, NULL, OPTION_DEBUG},
164   { "mno-debug",   no_argument, NULL, OPTION_NODEBUG},
165   { "mlibrary",    no_argument, NULL, OPTION_LIBRARY},
166   { NULL, 0, NULL, 0 } };
167 size_t md_longopts_size = sizeof (md_longopts);
168
169 const char * md_shortopts = "";
170 static int optbits = 0;
171 static int optbitset = 0;
172
173 int
174 md_parse_option (int c, char *arg ATTRIBUTE_UNUSED)
175 {
176   int i, idx;
177   switch (c)
178     {
179     case OPTION_EB:
180       target_big_endian = 1;
181       break;
182     case OPTION_EL:
183       target_big_endian = 0;
184       break;
185     case OPTION_CONFIG:
186       idx = 0;
187       for (i=1; mep_config_map[i].name; i++)
188         if (strcmp (mep_config_map[i].name, arg) == 0)
189           {
190             idx = i;
191             break;
192           }
193       if (!idx)
194         {
195           fprintf (stderr, "Error: unknown configuration %s\n", arg);
196           return 0;
197         }
198       mep_config_index = idx;
199       target_big_endian = mep_config_map[idx].big_endian;
200       break;
201     case OPTION_AVERAGE:
202       optbits |= 1 << CGEN_INSN_OPTIONAL_AVE_INSN;
203       optbitset |= 1 << CGEN_INSN_OPTIONAL_AVE_INSN;
204       break;
205     case OPTION_NOAVERAGE:
206       optbits &= ~(1 << CGEN_INSN_OPTIONAL_AVE_INSN);
207       optbitset |= 1 << CGEN_INSN_OPTIONAL_AVE_INSN;
208       break;
209     case OPTION_MULT:
210       optbits |= 1 << CGEN_INSN_OPTIONAL_MUL_INSN;
211       optbitset |= 1 << CGEN_INSN_OPTIONAL_MUL_INSN;
212       break;
213     case OPTION_NOMULT:
214       optbits &= ~(1 << CGEN_INSN_OPTIONAL_MUL_INSN);
215       optbitset |= 1 << CGEN_INSN_OPTIONAL_MUL_INSN;
216       break;
217     case OPTION_DIV:
218       optbits |= 1 << CGEN_INSN_OPTIONAL_DIV_INSN;
219       optbitset |= 1 << CGEN_INSN_OPTIONAL_DIV_INSN;
220       break;
221     case OPTION_NODIV:
222       optbits &= ~(1 << CGEN_INSN_OPTIONAL_DIV_INSN);
223       optbitset |= 1 << CGEN_INSN_OPTIONAL_DIV_INSN;
224       break;
225     case OPTION_BITOPS:
226       optbits |= 1 << CGEN_INSN_OPTIONAL_BIT_INSN;
227       optbitset |= 1 << CGEN_INSN_OPTIONAL_BIT_INSN;
228       break;
229     case OPTION_NOBITOPS:
230       optbits &= ~(1 << CGEN_INSN_OPTIONAL_BIT_INSN);
231       optbitset |= 1 << CGEN_INSN_OPTIONAL_BIT_INSN;
232       break;
233     case OPTION_LEADZ:
234       optbits |= 1 << CGEN_INSN_OPTIONAL_LDZ_INSN;
235       optbitset |= 1 << CGEN_INSN_OPTIONAL_LDZ_INSN;
236       break;
237     case OPTION_NOLEADZ:
238       optbits &= ~(1 << CGEN_INSN_OPTIONAL_LDZ_INSN);
239       optbitset |= 1 << CGEN_INSN_OPTIONAL_LDZ_INSN;
240       break;
241     case OPTION_ABSDIFF:
242       optbits |= 1 << CGEN_INSN_OPTIONAL_ABS_INSN;
243       optbitset |= 1 << CGEN_INSN_OPTIONAL_ABS_INSN;
244       break;
245     case OPTION_NOABSDIFF:
246       optbits &= ~(1 << CGEN_INSN_OPTIONAL_ABS_INSN);
247       optbitset |= 1 << CGEN_INSN_OPTIONAL_ABS_INSN;
248       break;
249     case OPTION_MINMAX:
250       optbits |= 1 << CGEN_INSN_OPTIONAL_MINMAX_INSN;
251       optbitset |= 1 << CGEN_INSN_OPTIONAL_MINMAX_INSN;
252       break;
253     case OPTION_NOMINMAX:
254       optbits &= ~(1 << CGEN_INSN_OPTIONAL_MINMAX_INSN);
255       optbitset |= 1 << CGEN_INSN_OPTIONAL_MINMAX_INSN;
256       break;
257     case OPTION_CLIP:
258       optbits |= 1 << CGEN_INSN_OPTIONAL_CLIP_INSN;
259       optbitset |= 1 << CGEN_INSN_OPTIONAL_CLIP_INSN;
260       break;
261     case OPTION_NOCLIP:
262       optbits &= ~(1 << CGEN_INSN_OPTIONAL_CLIP_INSN);
263       optbitset |= 1 << CGEN_INSN_OPTIONAL_CLIP_INSN;
264       break;
265     case OPTION_SATUR:
266       optbits |= 1 << CGEN_INSN_OPTIONAL_SAT_INSN;
267       optbitset |= 1 << CGEN_INSN_OPTIONAL_SAT_INSN;
268       break;
269     case OPTION_NOSATUR:
270       optbits &= ~(1 << CGEN_INSN_OPTIONAL_SAT_INSN);
271       optbitset |= 1 << CGEN_INSN_OPTIONAL_SAT_INSN;
272       break;
273     case OPTION_COP32:
274       optbits |= 1 << CGEN_INSN_OPTIONAL_CP_INSN;
275       optbitset |= 1 << CGEN_INSN_OPTIONAL_CP_INSN;
276       break;
277     case OPTION_DEBUG:
278       optbits |= 1 << CGEN_INSN_OPTIONAL_DEBUG_INSN;
279       optbitset |= 1 << CGEN_INSN_OPTIONAL_DEBUG_INSN;
280       break;
281     case OPTION_NODEBUG:
282       optbits &= ~(1 << CGEN_INSN_OPTIONAL_DEBUG_INSN);
283       optbitset |= 1 << CGEN_INSN_OPTIONAL_DEBUG_INSN;
284       break;
285     case OPTION_LIBRARY:
286       library_flag = EF_MEP_LIBRARY;
287       break;
288     case OPTION_REPEAT:
289     case OPTION_NOREPEAT:
290       break;
291     default:
292       return 0;
293     }
294   return 1;
295 }
296
297 void
298 md_show_usage (FILE *stream)
299 {
300   fprintf (stream, _("MeP specific command line options:\n\
301   -EB                     assemble for a big endian system (default)\n\
302   -EL                     assemble for a little endian system\n\
303   -mconfig=<name>         specify a chip configuration to use\n\
304   -maverage -mno-average -mmult -mno-mult -mdiv -mno-div\n\
305   -mbitops -mno-bitops -mleadz -mno-leadz -mabsdiff -mno-absdiff\n\
306   -mminmax -mno-minmax -mclip -mno-clip -msatur -mno-satur -mcop32\n\
307                           enable/disable the given opcodes\n\
308 \n\
309   If -mconfig is given, the other -m options modify it.  Otherwise,\n\
310   if no -m options are given, all core opcodes are enabled;\n\
311   if any enabling -m options are given, only those are enabled;\n\
312   if only disabling -m options are given, only those are disabled.\n\
313 "));
314   if (mep_config_map[1].name)
315     {
316       int i;
317       fprintf (stream, "  -mconfig=STR            specify the configuration to use\n");
318       fprintf (stream, "  Configurations:");
319       for (i=0; mep_config_map[i].name; i++)
320         fprintf (stream, " %s", mep_config_map[i].name);
321       fprintf (stream, "\n");
322     }
323 }
324
325 \f
326
327 static void
328 mep_check_for_disabled_registers (mep_insn *insn)
329 {
330   static int initted = 0;
331   static int has_mul_div = 0;
332   static int has_cop = 0;
333   static int has_debug = 0;
334   unsigned int b, r;
335
336   if (allow_disabled_registers)
337     return;
338
339 #if !CGEN_INT_INSN_P
340   if (target_big_endian)
341     b = insn->buffer[0] * 256 + insn->buffer[1];
342   else
343     b = insn->buffer[1] * 256 + insn->buffer[0];
344 #else
345   b = insn->buffer[0];
346 #endif
347
348   if ((b & 0xfffff00e) == 0x7008 /* stc */
349       || (b & 0xfffff00e) == 0x700a /* ldc */)
350     {
351       if (!initted)
352         {
353           initted = 1;
354           if ((MEP_OMASK & (1 << CGEN_INSN_OPTIONAL_MUL_INSN))
355               || (MEP_OMASK & (1 << CGEN_INSN_OPTIONAL_DIV_INSN)))
356             has_mul_div = 1;
357           if (MEP_OMASK & (1 << CGEN_INSN_OPTIONAL_DEBUG_INSN))
358             has_debug = 1;
359           if (MEP_OMASK & (1 << CGEN_INSN_OPTIONAL_CP_INSN))
360             has_cop = 1;
361         }
362
363       r = ((b & 0x00f0) >> 4) | ((b & 0x0001) << 4);
364       switch (r)
365         {
366         case 7: /* $hi */
367         case 8: /* $lo */
368           if (!has_mul_div)
369             as_bad ("$hi and $lo are disabled when MUL and DIV are off");
370           break;
371         case 12: /* $mb0 */
372         case 13: /* $me0 */
373         case 14: /* $mb1 */
374         case 15: /* $me1 */
375           if (!has_cop)
376             as_bad ("$mb0, $me0, $mb1, and $me1 are disabled when COP is off");
377           break;
378         case 24: /* $dbg */
379         case 25: /* $depc */
380           if (!has_debug)
381             as_bad ("$dbg and $depc are disabled when DEBUG is off");
382           break;
383         }
384     }
385 }
386
387 static int
388 mep_machine (void)
389 {
390   switch (MEP_CPU)
391     {
392     default: break;
393     case EF_MEP_CPU_C2: return bfd_mach_mep;
394     case EF_MEP_CPU_C3: return bfd_mach_mep;
395     case EF_MEP_CPU_C4: return bfd_mach_mep;
396     case EF_MEP_CPU_H1: return bfd_mach_mep_h1;
397     }
398
399   return bfd_mach_mep;
400 }
401
402 /* The MeP version of the cgen parse_operand function.  The only difference
403    from the standard version is that we want to avoid treating '$foo' and
404    '($foo...)' as references to a symbol called '$foo'.  The chances are
405    that '$foo' is really a misspelt register.  */
406
407 static const char *
408 mep_parse_operand (CGEN_CPU_DESC cd, enum cgen_parse_operand_type want,
409                    const char **strP, int opindex, int opinfo,
410                    enum cgen_parse_operand_result *resultP, bfd_vma *valueP)
411 {
412   if (want == CGEN_PARSE_OPERAND_INTEGER || want == CGEN_PARSE_OPERAND_ADDRESS)
413     {
414       const char *next;
415
416       next = *strP;
417       while (*next == '(')
418         next++;
419       if (*next == '$')
420         return "Not a valid literal";
421     }
422   return gas_cgen_parse_operand (cd, want, strP, opindex, opinfo,
423                                  resultP, valueP);
424 }
425
426 void
427 md_begin ()
428 {
429   /* Initialize the `cgen' interface.  */
430
431   /* If the user specifies no options, we default to allowing
432      everything.  If the user specifies any enabling options, we
433      default to allowing only what is specified.  If the user
434      specifies only disabling options, we only disable what is
435      specified.  If the user specifies options and a config, the
436      options modify the config.  */
437   if (optbits && mep_config_index == 0)
438     MEP_OMASK = optbits;
439   else
440     MEP_OMASK = (MEP_OMASK & ~optbitset) | optbits;
441
442   /* Set the machine number and endian.  */
443   gas_cgen_cpu_desc = mep_cgen_cpu_open (CGEN_CPU_OPEN_MACHS, 0,
444                                          CGEN_CPU_OPEN_ENDIAN,
445                                          target_big_endian
446                                          ? CGEN_ENDIAN_BIG
447                                          : CGEN_ENDIAN_LITTLE,
448                                          CGEN_CPU_OPEN_ISAS, 0,
449                                          CGEN_CPU_OPEN_END);
450   mep_cgen_init_asm (gas_cgen_cpu_desc);
451
452   /* This is a callback from cgen to gas to parse operands.  */
453   cgen_set_parse_operand_fn (gas_cgen_cpu_desc, mep_parse_operand);
454
455   /* Identify the architecture.  */
456   bfd_default_set_arch_mach (stdoutput, bfd_arch_mep, mep_machine ());
457
458   /* Store the configuration number and core.  */
459   bfd_set_private_flags (stdoutput, MEP_CPU | MEP_CONFIG | library_flag);
460
461   /* Initialize the array we'll be using to store fixups.  */
462   gas_cgen_initialize_saved_fixups_array();
463 }
464
465 /* Variant of mep_cgen_assemble_insn.  Assemble insn STR of cpu CD as a 
466    coprocessor instruction, if possible, into FIELDS, BUF, and INSN.  */
467
468 static const CGEN_INSN *
469 mep_cgen_assemble_cop_insn (CGEN_CPU_DESC cd,
470                             const char *str,
471                             CGEN_FIELDS *fields,
472                             CGEN_INSN_BYTES_PTR buf,
473                             const struct cgen_insn *pinsn)
474 {
475   const char *start;
476   CGEN_INSN_LIST *ilist;
477   const char *errmsg = NULL;
478
479   /* The instructions are stored in hashed lists. */
480   ilist = CGEN_ASM_LOOKUP_INSN (gas_cgen_cpu_desc, 
481                                 CGEN_INSN_MNEMONIC (pinsn));
482
483   start = str;
484   for ( ; ilist != NULL ; ilist = CGEN_ASM_NEXT_INSN (ilist))
485     {
486       const CGEN_INSN *insn = ilist->insn;
487       if (strcmp (CGEN_INSN_MNEMONIC (ilist->insn), 
488                   CGEN_INSN_MNEMONIC (pinsn)) == 0
489           && MEP_INSN_COP_P (ilist->insn)
490           && mep_cgen_insn_supported (cd, insn))
491         {
492           str = start;
493
494           /* skip this insn if str doesn't look right lexically */
495           if (CGEN_INSN_RX (insn) != NULL &&
496               regexec ((regex_t *) CGEN_INSN_RX (insn), str, 0, NULL, 0) == REG_NOMATCH)
497             continue;
498
499           /* Allow parse/insert handlers to obtain length of insn.  */
500           CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn);
501
502           errmsg = CGEN_PARSE_FN (cd, insn) (cd, insn, & str, fields);
503           if (errmsg != NULL)
504             continue;
505           
506           errmsg = CGEN_INSERT_FN (cd, insn) (cd, insn, fields, buf,
507                                               (bfd_vma) 0);
508           if (errmsg != NULL)
509             continue;
510
511           return insn;
512         }
513     }
514   return pinsn;
515 }
516
517 static void
518 mep_save_insn (mep_insn insn)
519 {
520   /* Consider change MAX_SAVED_FIXUP_CHAINS to MAX_PARALLEL_INSNS. */
521   if (num_insns_saved < 0 || num_insns_saved >= MAX_SAVED_FIXUP_CHAINS)
522     {
523       as_fatal("index into saved_insns[] out of bounds.");
524       return;
525     }
526   saved_insns[num_insns_saved] = insn;
527   gas_cgen_save_fixups(num_insns_saved);
528   num_insns_saved++;
529 }
530
531 static void
532 mep_check_parallel32_scheduling (void)
533 {
534   int insn0iscopro, insn1iscopro, insn0length, insn1length;
535
536   /* More than two instructions means that either someone is referring to
537      an internally parallel core or an internally parallel coprocessor,
538      neither of which are supported at this time.  */
539   if ( num_insns_saved > 2 )
540     as_fatal("Internally paralled cores and coprocessors not supported.");
541
542   /* If there are no insns saved, that's ok.  Just return.  This will
543      happen when mep_process_saved_insns is called when the end of the
544      source file is reached and there are no insns left to be processed.  */
545   if (num_insns_saved == 0)
546     return;
547
548   /* Check some of the attributes of the first insn.  */
549   insn0iscopro = MEP_INSN_COP_P (saved_insns[0].insn);
550   insn0length = CGEN_FIELDS_BITSIZE (& saved_insns[0].fields);
551
552   if (num_insns_saved == 2)
553     {
554       /* Check some of the attributes of the first insn.  */
555       insn1iscopro = MEP_INSN_COP_P (saved_insns[1].insn);
556       insn1length = CGEN_FIELDS_BITSIZE (& saved_insns[1].fields);
557
558       if ((insn0iscopro && !insn1iscopro)
559           || (insn1iscopro && !insn0iscopro))
560         {
561           /* We have one core and one copro insn.  If their sizes
562              add up to 32, then the combination is valid.  */
563           if (insn0length + insn1length == 32)
564             return;
565           else
566             as_bad ("core and copro insn lengths must total 32 bits.");
567         }
568       else
569         as_bad ("vliw group must consist of 1 core and 1 copro insn."); 
570     }
571   else
572     {
573       /* If we arrive here, we have one saved instruction.  There are a
574          number of possible cases:
575
576          1.  The instruction is a 32 bit core or coprocessor insn and
577              can be executed by itself.  Valid.
578
579          2.  The instrucion is a core instruction for which a cop nop
580              exists.  In this case, insert the cop nop into the saved
581              insn array after the core insn and return.  Valid.
582
583          3.  The instruction is a coprocessor insn for which a core nop
584              exists.  In this case, move the coprocessor insn to the
585              second element of the array and put the nop in the first
586              element then return.  Valid.
587
588          4. The instruction is a core or coprocessor instruction for
589             which there is no matching coprocessor or core nop to use
590             to form a valid vliw insn combination.  In this case, we
591             we have to abort.  */
592
593       if (insn0length > 32)
594         as_fatal ("Cannot use 48- or 64-bit insns with a 32 bit datapath.");
595
596       if (insn0length == 32)
597         return;
598
599       /* Insn is smaller than datapath.  If there are no matching
600          nops for this insn, then terminate assembly.  */
601       if (CGEN_INSN_ATTR_VALUE (saved_insns[0].insn,
602                                 CGEN_INSN_VLIW32_NO_MATCHING_NOP))
603         as_fatal ("No valid nop.");
604
605       /* At this point we know that we have a single 16-bit insn that has 
606          a matching nop.  We have to assemble it and put it into the saved 
607          insn and fixup chain arrays. */
608
609       if (insn0iscopro)
610         {
611           char *errmsg;
612           mep_insn insn;
613          
614           /* Move the insn and it's fixups to the second element of the
615              saved insns arrary and insert a 16 bit core nope into the
616              first element. */
617              insn.insn = mep_cgen_assemble_insn (gas_cgen_cpu_desc, "nop",
618                                                  &insn.fields, insn.buffer,
619                                                  &errmsg);
620              if (!insn.insn)
621                {
622                  as_bad ("%s", errmsg);
623                  return;
624                }
625
626              /* Move the insn in element 0 to element 1 and insert the
627                  nop into element 0.  Move the fixups in element 0 to
628                  element 1 and save the current fixups to element 0.  
629                  Really there aren't any fixups at this point because we're
630                  inserting a nop but we might as well be general so that
631                  if there's ever a need to insert a general insn, we'll
632                  have an example. */
633               saved_insns[1] = saved_insns[0];
634               saved_insns[0] = insn;
635               num_insns_saved++;
636               gas_cgen_swap_fixups (0);
637               gas_cgen_save_fixups (1);
638         }
639       else
640         {
641           char * errmsg;
642           mep_insn insn;
643           int insn_num = saved_insns[0].insn->base->num;
644
645           /* Use 32 bit branches and skip the nop.  */
646           if (insn_num == MEP_INSN_BSR12
647               || insn_num == MEP_INSN_BEQZ
648               || insn_num == MEP_INSN_BNEZ)
649             return;
650
651           /* Insert a 16-bit coprocessor nop.  Note that at the time */
652           /* this was done, no 16-bit coprocessor nop was defined.   */
653           insn.insn = mep_cgen_assemble_insn (gas_cgen_cpu_desc, "cpnop16",
654                                               &insn.fields, insn.buffer,
655                                               &errmsg);
656           if (!insn.insn)
657             {
658               as_bad ("%s", errmsg);
659               return;
660             }
661
662           /* Now put the insn and fixups into the arrays.  */
663           mep_save_insn (insn);
664         }
665     }
666 }
667
668 static void
669 mep_check_parallel64_scheduling (void)
670 {
671   int insn0iscopro, insn1iscopro, insn0length, insn1length;
672
673   /* More than two instructions means that someone is referring to an
674      internally parallel core or an internally parallel coprocessor.  */
675   /* These are not currently supported.  */
676   if (num_insns_saved > 2)
677     as_fatal ("Internally parallel cores of coprocessors not supported.");
678
679   /* If there are no insns saved, that's ok.  Just return.  This will
680      happen when mep_process_saved_insns is called when the end of the
681      source file is reached and there are no insns left to be processed.  */
682   if (num_insns_saved == 0)
683     return;
684
685   /* Check some of the attributes of the first insn.  */
686   insn0iscopro = MEP_INSN_COP_P (saved_insns[0].insn);
687   insn0length = CGEN_FIELDS_BITSIZE (& saved_insns[0].fields);
688
689   if (num_insns_saved == 2)
690     {
691       /* Check some of the attributes of the first insn. */
692       insn1iscopro = MEP_INSN_COP_P (saved_insns[1].insn);
693       insn1length = CGEN_FIELDS_BITSIZE (& saved_insns[1].fields);
694
695       if ((insn0iscopro && !insn1iscopro)
696           || (insn1iscopro && !insn0iscopro))
697         {
698           /* We have one core and one copro insn.  If their sizes
699              add up to 64, then the combination is valid.  */
700           if (insn0length + insn1length == 64)
701             return;
702           else
703             as_bad ("core and copro insn lengths must total 64 bits.");
704         }
705       else
706         as_bad ("vliw group must consist of 1 core and 1 copro insn.");
707     }
708   else
709     {
710       /* If we arrive here, we have one saved instruction.  There are a
711          number of possible cases:
712
713          1.  The instruction is a 64 bit coprocessor insn and can be
714              executed by itself.  Valid.
715
716          2.  The instrucion is a core instruction for which a cop nop
717              exists.  In this case, insert the cop nop into the saved
718              insn array after the core insn and return.  Valid.
719
720          3.  The instruction is a coprocessor insn for which a core nop
721              exists.  In this case, move the coprocessor insn to the
722              second element of the array and put the nop in the first
723              element then return.  Valid.
724
725          4.  The instruction is a core or coprocessor instruction for
726              which there is no matching coprocessor or core nop to use
727              to form a valid vliw insn combination.  In this case, we
728              we have to abort.  */
729
730       /* If the insn is 64 bits long, it can run alone.  The size check
731          is done indepependantly of whether the insn is core or copro
732          in case 64 bit coprocessor insns are added later.  */
733       if (insn0length == 64)
734         return;
735
736       /* Insn is smaller than datapath.  If there are no matching
737          nops for this insn, then terminate assembly.  */
738       if (CGEN_INSN_ATTR_VALUE (saved_insns[0].insn,
739                                 CGEN_INSN_VLIW64_NO_MATCHING_NOP))
740         as_fatal ("No valid nop.");
741
742       if (insn0iscopro)
743         {
744           char *errmsg;
745           mep_insn insn;
746           int i;
747
748           /* Initialize the insn buffer.  */
749           for (i = 0; i < 64; i++)
750              insn.buffer[i] = '\0';
751
752           /* We have a coprocessor insn.  At this point in time there
753              are is 32-bit core nop.  There is only a 16-bit core
754              nop.  The idea is to allow for a relatively arbitrary
755              coprocessor to be specified.  We aren't looking at
756              trying to cover future changes in the core at this time
757              since it is assumed that the core will remain fairly
758              static.  If there ever are 32 or 48 bit core nops added,
759              they will require entries below.  */
760
761           if (insn0length == 48)
762             {
763               /* Move the insn and fixups to the second element of the
764                  arrays then assemble and insert a 16 bit core nop.  */
765               insn.insn = mep_cgen_assemble_insn (gas_cgen_cpu_desc, "nop",
766                                                   & insn.fields, insn.buffer,
767                                                   & errmsg);
768             }
769           else
770             {
771               /* If this is reached, then we have a single coprocessor
772                  insn that is not 48 bits long, but for which the assembler
773                  thinks there is a matching core nop.  If a 32-bit core
774                  nop has been added, then make the necessary changes and
775                  handle its assembly and insertion here.  Otherwise,
776                  go figure out why either:
777               
778                  1. The assembler thinks that there is a 32-bit core nop
779                     to match a 32-bit coprocessor insn, or
780                  2. The assembler thinks that there is a 48-bit core nop
781                     to match a 16-bit coprocessor insn.  */
782
783               as_fatal ("Assembler expects a non-existent core nop.");
784             }
785
786          if (!insn.insn)
787            {
788              as_bad ("%s", errmsg);
789              return;
790            }
791
792          /* Move the insn in element 0 to element 1 and insert the
793             nop into element 0.  Move the fixups in element 0 to
794             element 1 and save the current fixups to element 0. 
795             Really there aren't any fixups at this point because we're
796             inserting a nop but we might as well be general so that
797             if there's ever a need to insert a general insn, we'll
798             have an example. */
799
800          saved_insns[1] = saved_insns[0];
801          saved_insns[0] = insn;
802          num_insns_saved++;
803          gas_cgen_swap_fixups(0);
804          gas_cgen_save_fixups(1);
805
806         }
807       else
808         {
809           char * errmsg;
810           mep_insn insn;
811           int i;
812
813           /* Initialize the insn buffer */
814           for (i = 0; i < 64; i++)
815              insn.buffer[i] = '\0';
816
817           /* We have a core insn.  We have to handle all possible nop
818              lengths.  If a coprocessor doesn't have a nop of a certain
819              length but there exists core insns that when combined with
820               a nop of that length would fill the datapath, those core
821               insns will be flagged with the VLIW_NO_CORRESPONDING_NOP
822               attribute.  That will ensure that when used in a way that
823               requires a nop to be inserted, assembly will terminate
824               before reaching this section of code.  This guarantees
825               that cases below which would result in the attempted
826               insertion of nop that doesn't exist will never be entered.  */
827           if (insn0length == 16)
828             {
829               /* Insert 48 bit coprocessor nop.          */
830               /* Assemble it and put it into the arrays. */
831               insn.insn = mep_cgen_assemble_insn (gas_cgen_cpu_desc, "cpnop48",
832                                                   &insn.fields, insn.buffer,
833                                                   &errmsg);
834             }
835           else if (insn0length == 32)
836             {
837               /* Insert 32 bit coprocessor nop. */
838               insn.insn = mep_cgen_assemble_insn (gas_cgen_cpu_desc, "cpnop32",
839                                                   &insn.fields, insn.buffer,
840                                                   &errmsg);
841             }
842           else if (insn0length == 48)
843             {
844               /* Insert 16 bit coprocessor nop. */
845               insn.insn = mep_cgen_assemble_insn (gas_cgen_cpu_desc, "cpnop16",
846                                                   &insn.fields, insn.buffer,
847                                                   &errmsg);
848             }
849           else
850             /* Core insn has an invalid length.  Something has gone wrong. */
851             as_fatal ("Core insn has invalid length!  Something is wrong!");
852
853           if (!insn.insn)
854             {
855               as_bad ("%s", errmsg);
856               return;
857             }
858
859           /* Now put the insn and fixups into the arrays.  */
860           mep_save_insn (insn);
861         }
862     }
863 }
864
865 /* The scheduling functions are just filters for invalid combinations.
866    If there is a violation, they terminate assembly.  Otherise they
867    just fall through.  Succesful combinations cause no side effects
868    other than valid nop insertion.  */
869
870 static void
871 mep_check_parallel_scheduling (void)
872 {
873   /* This is where we will eventually read the config information
874      and choose which scheduling checking function to call.  */   
875   if (MEP_VLIW64)
876     mep_check_parallel64_scheduling ();
877   else
878     mep_check_parallel32_scheduling ();
879 }
880
881 static void
882 mep_process_saved_insns (void)
883 {
884   int i;
885
886   gas_cgen_save_fixups (MAX_SAVED_FIXUP_CHAINS - 1);
887
888   /* We have to check for valid scheduling here. */
889   mep_check_parallel_scheduling ();
890
891   /* If the last call didn't cause assembly to terminate, we have
892      a valid vliw insn/insn pair saved. Restore this instructions'
893      fixups and process the insns. */
894   for (i = 0;i<num_insns_saved;i++)
895     {
896       gas_cgen_restore_fixups (i);
897       gas_cgen_finish_insn (saved_insns[i].insn, saved_insns[i].buffer,
898                             CGEN_FIELDS_BITSIZE (& saved_insns[i].fields),
899                             1, NULL);
900     }
901   gas_cgen_restore_fixups (MAX_SAVED_FIXUP_CHAINS - 1);
902
903   /* Clear the fixups and reset the number insn saved to 0. */
904   gas_cgen_initialize_saved_fixups_array ();
905   num_insns_saved = 0;
906   listing_prev_line ();
907 }
908
909 void
910 md_assemble (char * str)
911 {
912   static CGEN_BITSET* isas = NULL;
913   char * errmsg;
914
915   /* Initialize GAS's cgen interface for a new instruction.  */
916   gas_cgen_init_parse ();
917
918   /* There are two possible modes: core and vliw.  We have to assemble
919      differently for each.
920
921      Core Mode:  We assemble normally.  All instructions are on a
922                  single line and are made up of one mnemonic and one
923                  set of operands.
924      VLIW Mode:  Vliw combinations are indicated as follows:
925
926                        core insn
927                      + copro insn
928
929                  We want to handle the general case where more than
930                  one instruction can be preceeded by a +.  This will
931                  happen later if we add support for internally parallel
932                  coprocessors.  We'll make the parsing nice and general
933                  so that it can handle an arbitrary number of insns
934                  with leading +'s.  The actual checking for valid
935                  combinations is done elsewhere.  */
936
937   /* Initialize the isa to refer to the core.  */
938   if (isas == NULL)
939     isas = cgen_bitset_copy (& MEP_CORE_ISA);
940   else
941     {
942       cgen_bitset_clear (isas);
943       cgen_bitset_union (isas, & MEP_CORE_ISA, isas);
944     }
945   gas_cgen_cpu_desc->isas = isas;
946
947   if (mode == VLIW)
948     {
949       /* VLIW mode.  */
950
951       int thisInsnIsCopro = 0;
952       mep_insn insn;
953       int i;
954       
955       /* Initialize the insn buffer */
956         
957       if (! CGEN_INT_INSN_P)
958          for (i=0; i < CGEN_MAX_INSN_SIZE; i++)
959             insn.buffer[i]='\0';
960
961       /* Can't tell core / copro insns apart at parse time! */
962       cgen_bitset_union (isas, & MEP_COP_ISA, isas);
963
964       /* Assemble the insn so we can examine its attributes. */
965       insn.insn = mep_cgen_assemble_insn (gas_cgen_cpu_desc, str,
966                                           &insn.fields, insn.buffer,
967                                           &errmsg);
968       if (!insn.insn)
969         {
970           as_bad ("%s", errmsg);
971           return;
972         }
973       mep_check_for_disabled_registers (&insn);
974
975       /* Check to see if it's a coprocessor instruction. */
976       thisInsnIsCopro = MEP_INSN_COP_P (insn.insn);
977
978       if (!thisInsnIsCopro)
979         {
980           insn.insn = mep_cgen_assemble_cop_insn (gas_cgen_cpu_desc, str,
981                                                   &insn.fields, insn.buffer,
982                                                   insn.insn);
983           thisInsnIsCopro = MEP_INSN_COP_P (insn.insn);
984           mep_check_for_disabled_registers (&insn);
985         }
986
987       if (pluspresent)
988         {
989           /* A plus was present. */
990           /* Check for a + with a core insn and abort if found. */
991           if (!thisInsnIsCopro)
992             {
993               as_fatal("A core insn cannot be preceeded by a +.\n");
994               return;
995             }
996
997           if (num_insns_saved > 0)
998             {
999               /* There are insns in the queue. Add this one. */
1000               mep_save_insn (insn);
1001             }
1002           else
1003             {
1004               /* There are no insns in the queue and a plus is present.
1005                  This is a syntax error.  Let's not tolerate this.
1006                  We can relax this later if necessary.  */
1007               as_bad (_("Invalid use of parallelization operator."));
1008               return;
1009             }
1010         }
1011       else
1012         {
1013           /* No plus was present. */
1014           if (num_insns_saved > 0)
1015             {
1016               /* There are insns saved and we came across an insn without a
1017                  leading +.  That's the signal to process the saved insns
1018                  before proceeding then treat the current insn as the first
1019                  in a new vliw group.  */
1020               mep_process_saved_insns ();
1021               num_insns_saved = 0;
1022               /* mep_save_insn (insn); */
1023             }
1024           mep_save_insn (insn);
1025 #if 0
1026           else
1027             {
1028
1029               /* Core Insn. Add it to the beginning of the queue. */
1030               mep_save_insn (insn);
1031               /* gas_cgen_save_fixups(num_insns_saved); */
1032             }
1033 #endif
1034         }
1035
1036       pluspresent = 0;
1037     }
1038   else
1039     {
1040       /* Core mode.  */
1041
1042       /* Only single instructions are assembled in core mode. */
1043       mep_insn insn;
1044
1045       /* If a leading '+' was present, issue an error.
1046          That's not allowed in core mode. */
1047       if (pluspresent)
1048         {
1049           as_bad (_("Leading plus sign not allowed in core mode"));
1050           return;
1051         }
1052
1053       insn.insn = mep_cgen_assemble_insn
1054         (gas_cgen_cpu_desc, str, & insn.fields, insn.buffer, & errmsg);
1055
1056       if (!insn.insn)
1057         {
1058           as_bad ("%s", errmsg);
1059           return;
1060         }
1061       gas_cgen_finish_insn (insn.insn, insn.buffer,
1062                             CGEN_FIELDS_BITSIZE (& insn.fields), 1, NULL);
1063       mep_check_for_disabled_registers (&insn);
1064     }
1065 }
1066
1067 valueT
1068 md_section_align (segT segment, valueT size)
1069 {
1070   int align = bfd_get_section_alignment (stdoutput, segment);
1071   return ((size + (1 << align) - 1) & (-1 << align));
1072 }
1073
1074
1075 symbolS *
1076 md_undefined_symbol (char *name ATTRIBUTE_UNUSED)
1077 {
1078   return 0;
1079 }
1080 \f
1081 /* Interface to relax_segment.  */
1082
1083
1084 const relax_typeS md_relax_table[] =
1085 {
1086   /* The fields are:
1087      1) most positive reach of this state,
1088      2) most negative reach of this state,
1089      3) how many bytes this mode will have in the variable part of the frag
1090      4) which index into the table to try if we can't fit into this one.  */
1091   /* Note that we use "beq" because "jmp" has a peculiarity - it cannot
1092      jump to addresses with any bits 27..24 set.  So, we use beq as a
1093      17-bit pc-relative branch to avoid using jmp, just in case.  */
1094
1095   /* 0 */ {     0,      0, 0, 0 }, /* unused */
1096   /* 1 */ {     0,      0, 0, 0 }, /* marker for "don't know yet" */
1097
1098   /* 2 */ {  2047,  -2048, 0, 3 }, /* bsr12 */
1099   /* 3 */ {     0,      0, 2, 0 }, /* bsr16 */
1100
1101   /* 4 */ {  2047,  -2048, 0, 5 }, /* bra */
1102   /* 5 */ { 65535, -65536, 2, 6 }, /* beq $0,$0 */
1103   /* 6 */ {     0,      0, 2, 0 }, /* jmp24 */
1104
1105   /* 7 */ { 65535, -65536, 0, 8 }, /* beqi */
1106   /* 8 */ {     0,      0, 4, 0 }, /* bnei/jmp */
1107
1108   /* 9 */  {   127,   -128, 0, 10 }, /* beqz */
1109   /* 10 */ { 65535, -65536, 2, 11 }, /* beqi */
1110   /* 11 */ {     0,      0, 4,  0 }, /* bnei/jmp */
1111
1112   /* 12 */ { 65535, -65536, 0, 13 }, /* bnei */
1113   /* 13 */ {     0,      0, 4,  0 }, /* beqi/jmp */
1114
1115   /* 14 */ {   127,   -128, 0, 15 }, /* bnez */
1116   /* 15 */ { 65535, -65536, 2, 16 }, /* bnei */
1117   /* 16 */ {     0,      0, 4,  0 },  /* beqi/jmp */
1118
1119   /* 17 */ { 65535, -65536, 0, 13 }, /* bgei */
1120   /* 18 */ {     0,      0, 4,  0 },
1121   /* 19 */ { 65535, -65536, 0, 13 }, /* blti */
1122   /* 20 */ {     0,      0, 4,  0 },
1123   /* 19 */ { 65535, -65536, 0, 13 }, /* bcpeq */
1124   /* 20 */ {     0,      0, 4,  0 },
1125   /* 19 */ { 65535, -65536, 0, 13 }, /* bcpne */
1126   /* 20 */ {     0,      0, 4,  0 },
1127   /* 19 */ { 65535, -65536, 0, 13 }, /* bcpat */
1128   /* 20 */ {     0,      0, 4,  0 },
1129   /* 19 */ { 65535, -65536, 0, 13 }, /* bcpaf */
1130   /* 20 */ {     0,      0, 4,  0 }
1131 };
1132
1133 /* Pseudo-values for 64 bit "insns" which are combinations of two 32
1134    bit insns.  */
1135 typedef enum {
1136   MEP_PSEUDO64_NONE,
1137   MEP_PSEUDO64_16BITCC,
1138   MEP_PSEUDO64_32BITCC,
1139 } MepPseudo64Values;
1140
1141 static struct {
1142   int insn;
1143   int growth;
1144   int insn_for_extern;
1145 } subtype_mappings[] = {
1146   { 0, 0, 0 },
1147   { 0, 0, 0 },
1148   { MEP_INSN_BSR12, 0, MEP_INSN_BSR24 },
1149   { MEP_INSN_BSR24, 2, MEP_INSN_BSR24 },
1150   { MEP_INSN_BRA,   0, MEP_INSN_BRA   },
1151   { MEP_INSN_BEQ,   2, MEP_INSN_BEQ   },
1152   { MEP_INSN_JMP,   2, MEP_INSN_JMP   },
1153   { MEP_INSN_BEQI,  0, MEP_INSN_BEQI  },
1154   { -1,             4, MEP_PSEUDO64_32BITCC },
1155   { MEP_INSN_BEQZ,  0, MEP_INSN_BEQZ  },
1156   { MEP_INSN_BEQI,  2, MEP_INSN_BEQI  },
1157   { -1,             4, MEP_PSEUDO64_16BITCC },
1158   { MEP_INSN_BNEI,  0, MEP_INSN_BNEI  },
1159   { -1,             4, MEP_PSEUDO64_32BITCC },
1160   { MEP_INSN_BNEZ,  0, MEP_INSN_BNEZ  },
1161   { MEP_INSN_BNEI,  2, MEP_INSN_BNEI  },
1162   { -1,             4, MEP_PSEUDO64_16BITCC },
1163   { MEP_INSN_BGEI,  0, MEP_INSN_BGEI  },
1164   { -1,             4, MEP_PSEUDO64_32BITCC },
1165   { MEP_INSN_BLTI,  0, MEP_INSN_BLTI  },
1166   { -1,             4, MEP_PSEUDO64_32BITCC },
1167   { MEP_INSN_BCPEQ, 0, MEP_INSN_BCPEQ  },
1168   { -1,             4, MEP_PSEUDO64_32BITCC },
1169   { MEP_INSN_BCPNE, 0, MEP_INSN_BCPNE  },
1170   { -1,             4, MEP_PSEUDO64_32BITCC },
1171   { MEP_INSN_BCPAT, 0, MEP_INSN_BCPAT  },
1172   { -1,             4, MEP_PSEUDO64_32BITCC },
1173   { MEP_INSN_BCPAF, 0, MEP_INSN_BCPAF  },
1174   { -1,             4, MEP_PSEUDO64_32BITCC }
1175 };
1176 #define NUM_MAPPINGS (sizeof (subtype_mappings) / sizeof (subtype_mappings[0]))
1177
1178 void
1179 mep_prepare_relax_scan (fragS *fragP, offsetT *aim, relax_substateT this_state)
1180 {
1181   symbolS *symbolP = fragP->fr_symbol;
1182   if (symbolP && !S_IS_DEFINED (symbolP))
1183     *aim = 0;
1184   /* Adjust for MeP pcrel not being relative to the next opcode.  */
1185   *aim += 2 + md_relax_table[this_state].rlx_length;
1186 }
1187
1188 static int
1189 insn_to_subtype (int insn)
1190 {
1191   unsigned int i;
1192   for (i=0; i<NUM_MAPPINGS; i++)
1193     if (insn == subtype_mappings[i].insn)
1194       return i;
1195   abort ();
1196 }
1197
1198 /* Return an initial guess of the length by which a fragment must grow
1199    to hold a branch to reach its destination.  Also updates fr_type
1200    and fr_subtype as necessary.
1201
1202    Called just before doing relaxation.  Any symbol that is now
1203    undefined will not become defined.  The guess for fr_var is
1204    ACTUALLY the growth beyond fr_fix.  Whatever we do to grow fr_fix
1205    or fr_var contributes to our returned value.  Although it may not
1206    be explicit in the frag, pretend fr_var starts with a 0 value.  */
1207
1208 int
1209 md_estimate_size_before_relax (fragS * fragP, segT segment)
1210 {
1211   if (fragP->fr_subtype == 1)
1212     fragP->fr_subtype = insn_to_subtype (fragP->fr_cgen.insn->base->num);
1213
1214   if (S_GET_SEGMENT (fragP->fr_symbol) != segment)
1215     {
1216       int new_insn;
1217
1218       new_insn = subtype_mappings[fragP->fr_subtype].insn_for_extern;
1219       fragP->fr_subtype = insn_to_subtype (new_insn);
1220     }
1221
1222   if (MEP_VLIW && ! MEP_VLIW64
1223       && (bfd_get_section_flags (stdoutput, segment) & SEC_MEP_VLIW))
1224     {
1225       /* Use 32 bit branches for vliw32 so the vliw word is not split.  */
1226       switch (fragP->fr_cgen.insn->base->num)
1227         {
1228         case MEP_INSN_BSR12:
1229           fragP->fr_subtype = insn_to_subtype 
1230             (subtype_mappings[fragP->fr_subtype].insn_for_extern);
1231           break;
1232         case MEP_INSN_BEQZ:
1233           fragP->fr_subtype ++;
1234           break;
1235         case MEP_INSN_BNEZ:
1236           fragP->fr_subtype ++;
1237           break;
1238         }
1239     }
1240
1241   if (fragP->fr_cgen.insn->base
1242       && fragP->fr_cgen.insn->base->num
1243          != subtype_mappings[fragP->fr_subtype].insn)
1244     {
1245       int new_insn= subtype_mappings[fragP->fr_subtype].insn;
1246       if (new_insn != -1)
1247         {
1248           fragP->fr_cgen.insn = (fragP->fr_cgen.insn
1249                                  - fragP->fr_cgen.insn->base->num
1250                                  + new_insn);
1251         }
1252     }
1253
1254   return subtype_mappings[fragP->fr_subtype].growth;
1255 }
1256
1257 /* *fragP has been relaxed to its final size, and now needs to have
1258    the bytes inside it modified to conform to the new size.
1259
1260    Called after relaxation is finished.
1261    fragP->fr_type == rs_machine_dependent.
1262    fragP->fr_subtype is the subtype of what the address relaxed to.  */
1263
1264 static int
1265 target_address_for (fragS *frag)
1266 {
1267   int rv = frag->fr_offset;
1268   symbolS *sym = frag->fr_symbol;
1269
1270   if (sym)
1271     rv += S_GET_VALUE (sym);
1272
1273   return rv;
1274 }
1275
1276 void
1277 md_convert_frag (bfd *abfd  ATTRIBUTE_UNUSED, 
1278                  segT sec ATTRIBUTE_UNUSED,
1279                  fragS *fragP)
1280 {
1281   int addend, rn, bit = 0;
1282   int operand;
1283   int where = fragP->fr_opcode - fragP->fr_literal;
1284   int e = target_big_endian ? 0 : 1;
1285
1286   addend = target_address_for (fragP) - (fragP->fr_address + where);
1287
1288   if (subtype_mappings[fragP->fr_subtype].insn == -1)
1289     {
1290       fragP->fr_fix += subtype_mappings[fragP->fr_subtype].growth;
1291       switch (subtype_mappings[fragP->fr_subtype].insn_for_extern)
1292         {
1293         case MEP_PSEUDO64_16BITCC:
1294           fragP->fr_opcode[1^e] = ((fragP->fr_opcode[1^e] & 1) ^ 1) | 0x06;
1295           fragP->fr_opcode[2^e] = 0xd8;
1296           fragP->fr_opcode[3^e] = 0x08;
1297           fragP->fr_opcode[4^e] = 0;
1298           fragP->fr_opcode[5^e] = 0;
1299           where += 2;
1300           break;
1301         case MEP_PSEUDO64_32BITCC:
1302           if (fragP->fr_opcode[0^e] & 0x10)
1303             fragP->fr_opcode[1^e] ^= 0x01;
1304           else
1305             fragP->fr_opcode[1^e] ^= 0x04;
1306           fragP->fr_opcode[2^e] = 0;
1307           fragP->fr_opcode[3^e] = 4;
1308           fragP->fr_opcode[4^e] = 0xd8;
1309           fragP->fr_opcode[5^e] = 0x08;
1310           fragP->fr_opcode[6^e] = 0;
1311           fragP->fr_opcode[7^e] = 0;
1312           where += 4;
1313           break;
1314         default:
1315           abort ();
1316         }
1317       fragP->fr_cgen.insn = (fragP->fr_cgen.insn
1318                              - fragP->fr_cgen.insn->base->num
1319                              + MEP_INSN_JMP);
1320       operand = MEP_OPERAND_PCABS24A2;
1321     }
1322   else
1323     switch (fragP->fr_cgen.insn->base->num)
1324       {
1325       case MEP_INSN_BSR12:
1326         fragP->fr_opcode[0^e] = 0xb0 | ((addend >> 8) & 0x0f);
1327         fragP->fr_opcode[1^e] = 0x01 | (addend & 0xfe);
1328         operand = MEP_OPERAND_PCREL12A2;
1329         break;
1330
1331       case MEP_INSN_BSR24:
1332         fragP->fr_fix += 2;
1333         fragP->fr_opcode[0^e] = 0xd8 | ((addend >> 5) & 0x07);
1334         fragP->fr_opcode[1^e] = 0x09 | ((addend << 3) & 0xf0);
1335         fragP->fr_opcode[2^e] = 0x00 | ((addend >>16) & 0xff);
1336         fragP->fr_opcode[3^e] = 0x00 | ((addend >> 8) & 0xff);
1337         operand = MEP_OPERAND_PCREL24A2;
1338         break;
1339
1340       case MEP_INSN_BRA:
1341         fragP->fr_opcode[0^e] = 0xb0 | ((addend >> 8) & 0x0f);
1342         fragP->fr_opcode[1^e] = 0x00 | (addend & 0xfe);
1343         operand = MEP_OPERAND_PCREL12A2;
1344         break;
1345
1346       case MEP_INSN_BEQ:
1347         /* The default relax_frag doesn't change the state if there is no
1348            growth, so we must manually handle converting out-of-range BEQ
1349            instructions to JMP.  */
1350         if (addend <= 65535 && addend >= -65536)
1351           {
1352             fragP->fr_fix += 2;
1353             fragP->fr_opcode[0^e] = 0xe0;
1354             fragP->fr_opcode[1^e] = 0x01;
1355             fragP->fr_opcode[2^e] = 0x00 | ((addend >> 9) & 0xff);
1356             fragP->fr_opcode[3^e] = 0x00 | ((addend >> 1) & 0xff);
1357             operand = MEP_OPERAND_PCREL17A2;
1358             break;
1359           }
1360         /* ...FALLTHROUGH... */
1361
1362       case MEP_INSN_JMP:
1363         addend = target_address_for (fragP);
1364         fragP->fr_fix += 2;
1365         fragP->fr_opcode[0^e] = 0xd8 | ((addend >> 5) & 0x07);
1366         fragP->fr_opcode[1^e] = 0x08 | ((addend << 3) & 0xf0);
1367         fragP->fr_opcode[2^e] = 0x00 | ((addend >>16) & 0xff);
1368         fragP->fr_opcode[3^e] = 0x00 | ((addend >> 8) & 0xff);
1369         operand = MEP_OPERAND_PCABS24A2;
1370         break;
1371
1372       case MEP_INSN_BNEZ:
1373         bit = 1;
1374       case MEP_INSN_BEQZ:
1375         fragP->fr_opcode[1^e] = bit | (addend & 0xfe);
1376         operand = MEP_OPERAND_PCREL8A2;
1377         break;
1378
1379       case MEP_INSN_BNEI:
1380         bit = 4;
1381       case MEP_INSN_BEQI:
1382         if (subtype_mappings[fragP->fr_subtype].growth)
1383           {
1384             fragP->fr_fix += subtype_mappings[fragP->fr_subtype].growth;
1385             rn = fragP->fr_opcode[0^e] & 0x0f;
1386             fragP->fr_opcode[0^e] = 0xe0 | rn;
1387             fragP->fr_opcode[1^e] = bit;
1388           }
1389         fragP->fr_opcode[2^e] = 0x00 | ((addend >> 9) & 0xff);
1390         fragP->fr_opcode[3^e] = 0x00 | ((addend >> 1) & 0xff);
1391         operand = MEP_OPERAND_PCREL17A2;
1392         break;
1393
1394       case MEP_INSN_BLTI:
1395       case MEP_INSN_BGEI:
1396       case MEP_INSN_BCPEQ:
1397       case MEP_INSN_BCPNE:
1398       case MEP_INSN_BCPAT:
1399       case MEP_INSN_BCPAF:
1400         /* No opcode change needed, just operand.  */
1401         fragP->fr_opcode[2^e] = (addend >> 9) & 0xff;
1402         fragP->fr_opcode[3^e] = (addend >> 1) & 0xff;
1403         operand = MEP_OPERAND_PCREL17A2;
1404         break;
1405
1406       default:
1407         abort ();
1408       }
1409
1410   if (S_GET_SEGMENT (fragP->fr_symbol) != sec
1411       || operand == MEP_OPERAND_PCABS24A2)
1412     {
1413       assert (fragP->fr_cgen.insn != 0);
1414       gas_cgen_record_fixup (fragP,
1415                              where,
1416                              fragP->fr_cgen.insn,
1417                              (fragP->fr_fix - where) * 8,
1418                              cgen_operand_lookup_by_num (gas_cgen_cpu_desc,
1419                                                          operand),
1420                              fragP->fr_cgen.opinfo,
1421                              fragP->fr_symbol, fragP->fr_offset);
1422     }
1423 }
1424
1425 \f
1426 /* Functions concerning relocs.  */
1427
1428 void
1429 mep_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
1430 {
1431   /* If we already know the fixup value, adjust it in the same
1432      way that the linker would have done.  */
1433   if (fixP->fx_addsy == 0)
1434     switch (fixP->fx_cgen.opinfo)
1435       {
1436       case BFD_RELOC_MEP_LOW16:
1437         *valP = ((long)(*valP & 0xffff)) << 16 >> 16;
1438         break;
1439       case BFD_RELOC_MEP_HI16U:
1440         *valP >>= 16;
1441         break;
1442       case BFD_RELOC_MEP_HI16S:
1443         *valP = (*valP + 0x8000) >> 16;
1444         break;
1445       }
1446
1447   /* Now call cgen's md_aply_fix.  */
1448   gas_cgen_md_apply_fix (fixP, valP, seg);
1449 }
1450
1451 long
1452 md_pcrel_from_section (fixS *fixP, segT sec)
1453 {
1454   if (fixP->fx_addsy != (symbolS *) NULL
1455       && (! S_IS_DEFINED (fixP->fx_addsy)
1456           || S_GET_SEGMENT (fixP->fx_addsy) != sec))
1457     /* The symbol is undefined (or is defined but not in this section).
1458        Let the linker figure it out.  */
1459     return 0;
1460
1461   /* Return the address of the opcode - cgen adjusts for opcode size
1462      itself, to be consistent with the disassembler, which must do
1463      so.  */
1464   return fixP->fx_where + fixP->fx_frag->fr_address;
1465 }
1466
1467 /* Return the bfd reloc type for OPERAND of INSN at fixup FIXP.
1468    Returns BFD_RELOC_NONE if no reloc type can be found.
1469    *FIXP may be modified if desired.  */
1470
1471 #if defined (__STDC__) || defined (ALMOST_STDC) || defined (HAVE_STRINGIZE)
1472 #define MAP(n) case MEP_OPERAND_##n: return BFD_RELOC_MEP_##n;
1473 #else
1474 #define MAP(n) case MEP_OPERAND_/**/n: return BFD_RELOC_MEP_/**/n;
1475 #endif
1476
1477 bfd_reloc_code_real_type
1478 md_cgen_lookup_reloc (const CGEN_INSN *insn ATTRIBUTE_UNUSED,
1479                       const CGEN_OPERAND *operand,
1480                       fixS *fixP)
1481 {
1482   enum bfd_reloc_code_real reloc = fixP->fx_cgen.opinfo;
1483   static char printed[MEP_OPERAND_MAX] = { 0 };
1484
1485   /* If there's a reloc here, it's because the parser saw a %foo() and
1486      is giving us the correct reloc to use, or because we converted to
1487      a different size reloc below and want to avoid "converting" more
1488      than once.  */
1489   if (reloc && reloc != BFD_RELOC_NONE)
1490     return reloc;
1491
1492   switch (operand->type)
1493     {
1494       MAP (PCREL8A2);   /* beqz */
1495       MAP (PCREL12A2);  /* bsr16 */
1496       MAP (PCREL17A2);  /* beqi */
1497       MAP (PCREL24A2);  /* bsr24 */
1498       MAP (PCABS24A2);  /* jmp */
1499       MAP (UIMM24);     /* mov */
1500       MAP (ADDR24A4);   /* sw/lw */
1501
1502     /* The rest of the relocs should be generated by the parser,
1503        for things such as %tprel(), etc. */
1504     case MEP_OPERAND_SIMM16:
1505 #ifdef OBJ_COMPLEX_RELC
1506       /* coalescing this into RELOC_MEP_16 is actually a bug,
1507          since it's a signed operand. let the relc code handle it. */
1508       return BFD_RELOC_RELC; 
1509 #endif
1510
1511     case MEP_OPERAND_UIMM16:
1512     case MEP_OPERAND_SDISP16:
1513     case MEP_OPERAND_CODE16:
1514       fixP->fx_where += 2;
1515       /* to avoid doing the above add twice */
1516       fixP->fx_cgen.opinfo = BFD_RELOC_MEP_16;
1517       return BFD_RELOC_MEP_16;
1518
1519     default:
1520 #ifdef OBJ_COMPLEX_RELC
1521       /* this is not an error, yet. 
1522          pass it to the linker. */
1523       return BFD_RELOC_RELC;
1524 #endif
1525       if (printed[operand->type])
1526         return BFD_RELOC_NONE;
1527       printed[operand->type] = 1;
1528
1529       as_bad_where (fixP->fx_file, fixP->fx_line,
1530                     _("Don't know how to relocate plain operands of type %s"),
1531                     operand->name);
1532
1533       /* Print some helpful hints for the user.  */
1534       switch (operand->type)
1535         {
1536         case MEP_OPERAND_UDISP7:
1537         case MEP_OPERAND_UDISP7A2:
1538         case MEP_OPERAND_UDISP7A4:
1539           as_bad_where (fixP->fx_file, fixP->fx_line,
1540                         _("Perhaps you are missing %%tpoff()?"));
1541           break;
1542         default:
1543           break;
1544         }
1545       return BFD_RELOC_NONE;
1546     }
1547 }
1548
1549 /* Called while parsing an instruction to create a fixup.
1550    We need to check for HI16 relocs and queue them up for later sorting.  */
1551
1552 fixS *
1553 mep_cgen_record_fixup_exp (fragS *frag,
1554                            int where,
1555                            const CGEN_INSN *insn,
1556                            int length,
1557                            const CGEN_OPERAND *operand,
1558                            int opinfo,
1559                            expressionS *exp)
1560 {
1561   fixS * fixP = gas_cgen_record_fixup_exp (frag, where, insn, length,
1562                                            operand, opinfo, exp);
1563   return fixP;
1564 }
1565
1566 /* Return BFD reloc type from opinfo field in a fixS.
1567    It's tricky using fx_r_type in mep_frob_file because the values
1568    are BFD_RELOC_UNUSED + operand number.  */
1569 #define FX_OPINFO_R_TYPE(f) ((f)->fx_cgen.opinfo)
1570
1571 /* Sort any unmatched HI16 relocs so that they immediately precede
1572    the corresponding LO16 reloc.  This is called before md_apply_fix and
1573    tc_gen_reloc.  */
1574
1575 void
1576 mep_frob_file ()
1577 {
1578   struct mep_hi_fixup * l;
1579
1580   for (l = mep_hi_fixup_list; l != NULL; l = l->next)
1581     {
1582       segment_info_type * seginfo;
1583       int pass;
1584
1585       assert (FX_OPINFO_R_TYPE (l->fixp) == BFD_RELOC_HI16
1586               || FX_OPINFO_R_TYPE (l->fixp) == BFD_RELOC_LO16);
1587
1588       /* Check quickly whether the next fixup happens to be a matching low.  */
1589       if (l->fixp->fx_next != NULL
1590           && FX_OPINFO_R_TYPE (l->fixp->fx_next) == BFD_RELOC_LO16
1591           && l->fixp->fx_addsy == l->fixp->fx_next->fx_addsy
1592           && l->fixp->fx_offset == l->fixp->fx_next->fx_offset)
1593         continue;
1594
1595       /* Look through the fixups for this segment for a matching
1596          `low'.  When we find one, move the high just in front of it.
1597          We do this in two passes.  In the first pass, we try to find
1598          a unique `low'.  In the second pass, we permit multiple
1599          high's relocs for a single `low'.  */
1600       seginfo = seg_info (l->seg);
1601       for (pass = 0; pass < 2; pass++)
1602         {
1603           fixS * f;
1604           fixS * prev;
1605
1606           prev = NULL;
1607           for (f = seginfo->fix_root; f != NULL; f = f->fx_next)
1608             {
1609               /* Check whether this is a `low' fixup which matches l->fixp.  */
1610               if (FX_OPINFO_R_TYPE (f) == BFD_RELOC_LO16
1611                   && f->fx_addsy == l->fixp->fx_addsy
1612                   && f->fx_offset == l->fixp->fx_offset
1613                   && (pass == 1
1614                       || prev == NULL
1615                       || (FX_OPINFO_R_TYPE (prev) != BFD_RELOC_HI16)
1616                       || prev->fx_addsy != f->fx_addsy
1617                       || prev->fx_offset !=  f->fx_offset))
1618                 {
1619                   fixS ** pf;
1620
1621                   /* Move l->fixp before f.  */
1622                   for (pf = &seginfo->fix_root;
1623                        * pf != l->fixp;
1624                        pf = & (* pf)->fx_next)
1625                     assert (* pf != NULL);
1626
1627                   * pf = l->fixp->fx_next;
1628
1629                   l->fixp->fx_next = f;
1630                   if (prev == NULL)
1631                     seginfo->fix_root = l->fixp;
1632                   else
1633                     prev->fx_next = l->fixp;
1634
1635                   break;
1636                 }
1637
1638               prev = f;
1639             }
1640
1641           if (f != NULL)
1642             break;
1643
1644           if (pass == 1)
1645             as_warn_where (l->fixp->fx_file, l->fixp->fx_line,
1646                            _("Unmatched high relocation"));
1647         }
1648     }
1649 }
1650
1651 /* See whether we need to force a relocation into the output file. */
1652
1653 int
1654 mep_force_relocation (fixS *fixp)
1655 {
1656   if (   fixp->fx_r_type == BFD_RELOC_VTABLE_INHERIT
1657          || fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
1658     return 1;
1659
1660   /* Allow branches to global symbols to be resolved at assembly time.
1661      This is consistent with way relaxable branches are handled, since
1662      branches to both global and local symbols are relaxed.  It also
1663      corresponds to the assumptions made in md_pcrel_from_section.  */
1664   return S_FORCE_RELOC (fixp->fx_addsy, !fixp->fx_pcrel);
1665 }
1666 \f
1667 /* Write a value out to the object file, using the appropriate endianness.  */
1668
1669 void
1670 md_number_to_chars (char *buf, valueT val, int n)
1671 {
1672   if (target_big_endian)
1673     number_to_chars_bigendian (buf, val, n);
1674   else
1675     number_to_chars_littleendian (buf, val, n);
1676 }
1677
1678 /* Turn a string in input_line_pointer into a floating point constant
1679    of type type, and store the appropriate bytes in *litP.  The number
1680    of LITTLENUMS emitted is stored in *sizeP .  An error message is
1681    returned, or NULL on OK. */
1682
1683 /* Equal to MAX_PRECISION in atof-ieee.c */
1684 #define MAX_LITTLENUMS 6
1685
1686 char *
1687 md_atof (int type, char *litP, int *sizeP)
1688 {
1689   int              i;
1690   int              prec;
1691   LITTLENUM_TYPE   words [MAX_LITTLENUMS];
1692   char *           t;
1693
1694   switch (type)
1695     {
1696     case 'f':
1697     case 'F':
1698     case 's':
1699     case 'S':
1700       prec = 2;
1701       break;
1702
1703     case 'd':
1704     case 'D':
1705     case 'r':
1706     case 'R':
1707       prec = 4;
1708       break;
1709
1710     /* FIXME: Some targets allow other format chars for bigger sizes here.  */
1711     default:
1712       *sizeP = 0;
1713       return _("Bad call to md_atof()");
1714     }
1715
1716   t = atof_ieee (input_line_pointer, type, words);
1717   if (t)
1718     input_line_pointer = t;
1719   * sizeP = prec * sizeof (LITTLENUM_TYPE);
1720
1721   for (i = 0; i < prec; i++)
1722     {
1723       md_number_to_chars (litP, (valueT) words[i],
1724                           sizeof (LITTLENUM_TYPE));
1725       litP += sizeof (LITTLENUM_TYPE);
1726     }
1727
1728   return 0;
1729 }
1730
1731
1732 bfd_boolean
1733 mep_fix_adjustable (fixS *fixP)
1734 {
1735   bfd_reloc_code_real_type reloc_type;
1736
1737   if ((int) fixP->fx_r_type >= (int) BFD_RELOC_UNUSED)
1738     {
1739       const CGEN_INSN *insn = NULL;
1740       int opindex = (int) fixP->fx_r_type - (int) BFD_RELOC_UNUSED;
1741       const CGEN_OPERAND *operand
1742         = cgen_operand_lookup_by_num(gas_cgen_cpu_desc, opindex);
1743       reloc_type = md_cgen_lookup_reloc (insn, operand, fixP);
1744     }
1745   else
1746     reloc_type = fixP->fx_r_type;
1747
1748   if (fixP->fx_addsy == NULL)
1749     return 1;
1750
1751   /* Prevent all adjustments to global symbols. */
1752   if (S_IS_EXTERNAL (fixP->fx_addsy))
1753     return 0;
1754
1755   if (S_IS_WEAK (fixP->fx_addsy))
1756     return 0;
1757
1758   /* We need the symbol name for the VTABLE entries */
1759   if (reloc_type == BFD_RELOC_VTABLE_INHERIT
1760       || reloc_type == BFD_RELOC_VTABLE_ENTRY)
1761     return 0;
1762
1763   return 1;
1764 }
1765
1766 int
1767 mep_elf_section_letter (int letter, char **ptrmsg)
1768 {
1769   if (letter == 'v')
1770     return SHF_MEP_VLIW;
1771
1772   *ptrmsg = _("Bad .section directive: want a,v,w,x,M,S in string");
1773   return 0;
1774 }
1775
1776 flagword
1777 mep_elf_section_flags (flagword flags, int attr, int type ATTRIBUTE_UNUSED)
1778 {
1779   if (attr & SHF_MEP_VLIW)
1780     flags |= SEC_MEP_VLIW;
1781   return flags;
1782 }
1783
1784 /* In vliw mode, the default section is .vtext.  We have to be able
1785    to switch into .vtext using only the .vtext directive.  */
1786
1787 static segT
1788 mep_vtext_section (void)
1789 {
1790   static segT vtext_section;
1791
1792   if (! vtext_section)
1793     {
1794       flagword applicable = bfd_applicable_section_flags (stdoutput);
1795       vtext_section = subseg_new (VTEXT_SECTION_NAME, 0);
1796       bfd_set_section_flags (stdoutput, vtext_section,
1797                              applicable & (SEC_ALLOC | SEC_LOAD | SEC_RELOC
1798                                            | SEC_CODE | SEC_READONLY
1799                                            | SEC_MEP_VLIW));
1800     }
1801
1802   return vtext_section;
1803 }
1804
1805 static void
1806 mep_s_vtext (int ignore ATTRIBUTE_UNUSED)
1807 {
1808   int temp;
1809
1810   /* Record previous_section and previous_subsection.  */
1811   obj_elf_section_change_hook ();
1812
1813   temp = get_absolute_expression ();
1814   subseg_set (mep_vtext_section (), (subsegT) temp);
1815   demand_empty_rest_of_line ();
1816 }
1817
1818 static void
1819 mep_switch_to_core_mode (int dummy ATTRIBUTE_UNUSED)
1820 {
1821   mep_process_saved_insns ();
1822   pluspresent = 0;
1823   mode = CORE;
1824 }
1825
1826 static void
1827 mep_switch_to_vliw_mode (int dummy ATTRIBUTE_UNUSED)
1828 {
1829   if (! MEP_VLIW)
1830     as_bad (_(".vliw unavailable when VLIW is disabled."));
1831   mode = VLIW;
1832   /* Switch into .vtext here too. */
1833   /* mep_s_vtext(); */
1834 }
1835
1836 /* This is an undocumented pseudo-op used to disable gas's
1837    "disabled_registers" check.  Used for code which checks for those
1838    registers at runtime.  */
1839 static void
1840 mep_noregerr (int i ATTRIBUTE_UNUSED)
1841 {
1842   allow_disabled_registers = 1;
1843 }
1844
1845 /* mep_unrecognized_line: This is called when a line that can't be parsed
1846    is encountered.  We use it to check for a leading '+' sign which indicates
1847    that the current instruction is a coprocessor instruction that is to be
1848    parallelized with a previous core insn.  This function accepts the '+' and
1849    rejects all other characters that might indicate garbage at the beginning
1850    of the line.  The '+' character gets lost as the calling loop continues,
1851    so we need to indicate that we saw it.  */
1852
1853 int
1854 mep_unrecognized_line (int ch)
1855 {
1856   switch (ch)
1857     {
1858     case '+':
1859       pluspresent = 1;
1860       return 1; /* '+' indicates an instruction to be parallelized. */
1861     default:
1862       return 0; /* If it's not a '+', the line can't be parsed. */
1863     }
1864 }
1865
1866 void
1867 mep_cleanup (void)
1868 {
1869   /* Take care of any insns left to be parallelized when the file ends.
1870      This is mainly here to handle the case where the file ends with an
1871      insn preceeded by a + or the file ends unexpectedly.  */
1872   if (mode == VLIW)
1873     mep_process_saved_insns ();
1874 }
1875
1876 int
1877 mep_flush_pending_output (void)
1878 {
1879   if (mode == VLIW)
1880     {
1881       mep_process_saved_insns ();
1882       pluspresent = 0;
1883     }
1884
1885   return 1; 
1886 }