tc-mep.c revision 214634
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.  */
36typedef 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
55static int mode = CORE; /* Start in core mode. */
56static int pluspresent = 0;
57static int allow_disabled_registers = 0;
58static 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
63static mep_insn saved_insns[MAX_SAVED_FIXUP_CHAINS];
64static int num_insns_saved = 0;
65
66const char comment_chars[]        = "#";
67const char line_comment_chars[]   = ";#";
68const char line_separator_chars[] = ";";
69const char EXP_CHARS[]            = "eE";
70const char FLT_CHARS[]            = "dD";
71
72static void mep_switch_to_vliw_mode (int);
73static void mep_switch_to_core_mode (int);
74static void mep_s_vtext (int);
75static void mep_noregerr (int);
76
77/* The target specific pseudo-ops which we support.  */
78const 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
101struct 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.  */
109static struct mep_hi_fixup * mep_hi_fixup_list;
110
111
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
140struct 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 } };
167size_t md_longopts_size = sizeof (md_longopts);
168
169const char * md_shortopts = "";
170static int optbits = 0;
171static int optbitset = 0;
172
173int
174md_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
297void
298md_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
326
327static void
328mep_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
387static int
388mep_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
407static const char *
408mep_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
426void
427md_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
468static const CGEN_INSN *
469mep_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
517static void
518mep_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
531static void
532mep_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
668static void
669mep_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
870static void
871mep_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
881static void
882mep_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
909void
910md_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
1067valueT
1068md_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
1075symbolS *
1076md_undefined_symbol (char *name ATTRIBUTE_UNUSED)
1077{
1078  return 0;
1079}
1080
1081/* Interface to relax_segment.  */
1082
1083
1084const 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.  */
1135typedef enum {
1136  MEP_PSEUDO64_NONE,
1137  MEP_PSEUDO64_16BITCC,
1138  MEP_PSEUDO64_32BITCC,
1139} MepPseudo64Values;
1140
1141static 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
1178void
1179mep_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
1188static int
1189insn_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
1208int
1209md_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
1264static int
1265target_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
1276void
1277md_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
1426/* Functions concerning relocs.  */
1427
1428void
1429mep_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
1451long
1452md_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
1477bfd_reloc_code_real_type
1478md_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
1552fixS *
1553mep_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
1575void
1576mep_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
1653int
1654mep_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
1667/* Write a value out to the object file, using the appropriate endianness.  */
1668
1669void
1670md_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
1686char *
1687md_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
1732bfd_boolean
1733mep_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
1766int
1767mep_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
1776flagword
1777mep_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
1787static segT
1788mep_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
1805static void
1806mep_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
1818static void
1819mep_switch_to_core_mode (int dummy ATTRIBUTE_UNUSED)
1820{
1821  mep_process_saved_insns ();
1822  pluspresent = 0;
1823  mode = CORE;
1824}
1825
1826static void
1827mep_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.  */
1839static void
1840mep_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
1853int
1854mep_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
1866void
1867mep_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
1876int
1877mep_flush_pending_output (void)
1878{
1879  if (mode == VLIW)
1880    {
1881      mep_process_saved_insns ();
1882      pluspresent = 0;
1883    }
1884
1885  return 1;
1886}
1887