xref: /NextBSD/contrib/binutils/gas/config/tc-mep.c (revision eb1a5f8de9f7ea602c373a710f531abbf81141c4)
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 
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
md_parse_option(int c,char * arg ATTRIBUTE_UNUSED)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
md_show_usage(FILE * stream)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 
326 
327 static void
mep_check_for_disabled_registers(mep_insn * insn)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
mep_machine(void)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 *
mep_parse_operand(CGEN_CPU_DESC cd,enum cgen_parse_operand_type want,const char ** strP,int opindex,int opinfo,enum cgen_parse_operand_result * resultP,bfd_vma * valueP)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
md_begin()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 *
mep_cgen_assemble_cop_insn(CGEN_CPU_DESC cd,const char * str,CGEN_FIELDS * fields,CGEN_INSN_BYTES_PTR buf,const struct cgen_insn * pinsn)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
mep_save_insn(mep_insn insn)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
mep_check_parallel32_scheduling(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
mep_check_parallel64_scheduling(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
mep_check_parallel_scheduling(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
mep_process_saved_insns(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
md_assemble(char * str)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
md_section_align(segT segment,valueT size)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 *
md_undefined_symbol(char * name ATTRIBUTE_UNUSED)1076 md_undefined_symbol (char *name ATTRIBUTE_UNUSED)
1077 {
1078   return 0;
1079 }
1080 
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
mep_prepare_relax_scan(fragS * fragP,offsetT * aim,relax_substateT this_state)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
insn_to_subtype(int insn)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
md_estimate_size_before_relax(fragS * fragP,segT segment)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
target_address_for(fragS * frag)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
md_convert_frag(bfd * abfd ATTRIBUTE_UNUSED,segT sec ATTRIBUTE_UNUSED,fragS * fragP)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 
1426 /* Functions concerning relocs.  */
1427 
1428 void
mep_apply_fix(fixS * fixP,valueT * valP,segT seg ATTRIBUTE_UNUSED)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
md_pcrel_from_section(fixS * fixP,segT sec)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
md_cgen_lookup_reloc(const CGEN_INSN * insn ATTRIBUTE_UNUSED,const CGEN_OPERAND * operand,fixS * fixP)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 *
mep_cgen_record_fixup_exp(fragS * frag,int where,const CGEN_INSN * insn,int length,const CGEN_OPERAND * operand,int opinfo,expressionS * exp)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
mep_frob_file()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
mep_force_relocation(fixS * fixp)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 
1667 /* Write a value out to the object file, using the appropriate endianness.  */
1668 
1669 void
md_number_to_chars(char * buf,valueT val,int n)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 *
md_atof(int type,char * litP,int * sizeP)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
mep_fix_adjustable(fixS * fixP)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
mep_elf_section_letter(int letter,char ** ptrmsg)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
mep_elf_section_flags(flagword flags,int attr,int type ATTRIBUTE_UNUSED)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
mep_vtext_section(void)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
mep_s_vtext(int ignore ATTRIBUTE_UNUSED)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
mep_switch_to_core_mode(int dummy ATTRIBUTE_UNUSED)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
mep_switch_to_vliw_mode(int dummy ATTRIBUTE_UNUSED)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
mep_noregerr(int i ATTRIBUTE_UNUSED)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
mep_unrecognized_line(int ch)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
mep_cleanup(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
mep_flush_pending_output(void)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 }
1887