1 /* tc-metag.c -- Assembler for the Imagination Technologies Meta.
2    Copyright (C) 2013-2021 Free Software Foundation, Inc.
3    Contributed by Imagination Technologies Ltd.
4 
5    This file is part of GAS, the GNU Assembler.
6 
7    GAS is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3, or (at your option)
10    any later version.
11 
12    GAS is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
15    GNU General Public License for more details.
16 
17    You should have received a copy of the GNU General Public License
18    along with GAS; see the file COPYING.  If not, write to the Free
19    Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
20    02110-1301, USA.  */
21 
22 #include "as.h"
23 #include "subsegs.h"
24 #include "symcat.h"
25 #include "safe-ctype.h"
26 #include "hashtab.h"
27 
28 #include <stdio.h>
29 
30 #include "opcode/metag.h"
31 
32 const char comment_chars[]        = "!";
33 const char line_comment_chars[]   = "!#";
34 const char line_separator_chars[] = ";";
35 const char FLT_CHARS[]            = "rRsSfFdDxXpP";
36 const char EXP_CHARS[]            = "eE";
37 const char metag_symbol_chars[]   = "[";
38 
39 static char register_chars[256];
40 static char mnemonic_chars[256];
41 
42 #define is_register_char(x) (register_chars[(unsigned char) x])
43 #define is_mnemonic_char(x) (mnemonic_chars[(unsigned char) x])
44 #define is_whitespace_char(x) (((x) == ' ') || ((x) == '\t'))
45 #define is_space_char(x) ((x) == ' ')
46 
47 #define FPU_PREFIX_CHAR 'f'
48 #define DSP_PREFIX_CHAR 'd'
49 
50 /* Instruction mnemonics that need disambiguating with respect to prefixes.  */
51 #define FFB_INSN        "ffb"
52 #define DCACHE_INSN     "dcache"
53 #define DEFR_INSN       "defr"
54 
55 #define FPU_DOUBLE_CHAR 'd'
56 #define FPU_PAIR_CHAR   'l'
57 
58 #define DSP_DUAL_CHAR	'l'
59 
60 #define END_OF_INSN     '\0'
61 
62 /* Maximum length of a mnemonic including all suffixes.  */
63 #define MAX_MNEMONIC_LEN 16
64 /* Maximum length of a register name.  */
65 #define MAX_REG_LEN      17
66 
67 /* Addressing modes must be enclosed with square brackets.  */
68 #define ADDR_BEGIN_CHAR '['
69 #define ADDR_END_CHAR   ']'
70 /* Immediates must be prefixed with a hash.  */
71 #define IMM_CHAR        '#'
72 
73 #define COMMA           ','
74 #define PLUS            '+'
75 #define MINUS           '-'
76 
77 /* Short units are those that can be encoded with 2 bits.  */
78 #define SHORT_UNITS     "D0, D1, A0 or A1"
79 
80 static unsigned int mcpu_opt = CoreMeta12;
81 static unsigned int mfpu_opt = 0;
82 static unsigned int mdsp_opt = 0;
83 
84 const char * md_shortopts = "m:";
85 
86 struct option md_longopts[] =
87 {
88   {NULL, no_argument, NULL, 0}
89 };
90 size_t md_longopts_size = sizeof (md_longopts);
91 
92 /* Parser hash tables.  */
93 static htab_t mnemonic_htab;
94 static htab_t reg_htab;
95 static htab_t dsp_reg_htab;
96 static htab_t dsp_tmpl_reg_htab[2];
97 static htab_t scond_htab;
98 
99 #define GOT_NAME "__GLOBAL_OFFSET_TABLE__"
100 symbolS * GOT_symbol;
101 
102 enum fpu_insn_width {
103   FPU_WIDTH_SINGLE,
104   FPU_WIDTH_DOUBLE,
105   FPU_WIDTH_PAIR,
106 };
107 
108 #define FPU_ACTION_ABS_CHAR   'a'
109 #define FPU_ACTION_INV_CHAR   'i'
110 #define FPU_ACTION_QUIET_CHAR 'q'
111 #define FPU_ACTION_ZERO_CHAR  'z'
112 
113 #define FPU_ACTION_ABS        0x1
114 #define FPU_ACTION_INV        0x2
115 #define FPU_ACTION_QUIET      0x4
116 #define FPU_ACTION_ZERO       0x8
117 
118 enum dsp_insn_width {
119   DSP_WIDTH_SINGLE,
120   DSP_WIDTH_DUAL,
121 };
122 
123 #define DSP_ACTION_QR64_CHAR     'q'
124 #define DSP_ACTION_UMUL_CHAR     'u'
125 #define DSP_ACTION_ROUND_CHAR    'r'
126 #define DSP_ACTION_CLAMP9_CHAR   'g'
127 #define DSP_ACTION_CLAMP8_CHAR   'b'
128 #define DSP_ACTION_MOD_CHAR      'm'
129 #define DSP_ACTION_ACC_ZERO_CHAR 'z'
130 #define DSP_ACTION_ACC_ADD_CHAR  'p'
131 #define DSP_ACTION_ACC_SUB_CHAR  'n'
132 #define DSP_ACTION_OV_CHAR       'o'
133 
134 #define DSP_ACTION_QR64          0x001
135 #define DSP_ACTION_UMUL          0x002
136 #define DSP_ACTION_ROUND         0x004
137 #define DSP_ACTION_CLAMP9        0x008
138 #define DSP_ACTION_CLAMP8        0x010
139 #define DSP_ACTION_MOD           0x020
140 #define DSP_ACTION_ACC_ZERO      0x040
141 #define DSP_ACTION_ACC_ADD       0x080
142 #define DSP_ACTION_ACC_SUB       0x100
143 #define DSP_ACTION_OV            0x200
144 
145 #define DSP_DAOPPAME_8_CHAR    'b'
146 #define DSP_DAOPPAME_16_CHAR   'w'
147 #define DSP_DAOPPAME_TEMP_CHAR 't'
148 #define DSP_DAOPPAME_HIGH_CHAR 'h'
149 
150 #define DSP_DAOPPAME_8         0x1
151 #define DSP_DAOPPAME_16        0x2
152 #define DSP_DAOPPAME_TEMP      0x4
153 #define DSP_DAOPPAME_HIGH      0x8
154 
155 /* Structure holding information about a parsed instruction.  */
156 typedef struct {
157   /* Instruction type.  */
158   enum insn_type type;
159   /* Split condition code. */
160   enum scond_code scond;
161 
162   /* Instruction bits.  */
163   unsigned int bits;
164   /* Size of the instruction in bytes.  */
165   size_t len;
166 
167   /* FPU instruction encoding.  */
168   enum fpu_insn_width fpu_width;
169   unsigned int fpu_action_flags;
170 
171   /* DSP instruction encoding. */
172   enum dsp_insn_width dsp_width;
173   unsigned int dsp_action_flags;
174   unsigned int dsp_daoppame_flags;
175 
176   /* Reloc encoding information, maximum of one reloc per insn.  */
177   enum bfd_reloc_code_real reloc_type;
178   int reloc_pcrel;
179   expressionS reloc_exp;
180   unsigned int reloc_size;
181 } metag_insn;
182 
183 /* Structure holding information about a parsed addressing mode.  */
184 typedef struct {
185   const metag_reg *base_reg;
186   const metag_reg *offset_reg;
187 
188   expressionS exp;
189 
190   enum bfd_reloc_code_real reloc_type;
191 
192   /* Whether we have an immediate or not.  */
193   unsigned short immediate:1;
194   /* Whether or not the base register is updated.  */
195   unsigned short update:1;
196   /* Whether the operation uses the address pre or post increment.  */
197   unsigned short post_increment:1;
198   /* Whether the immediate should be negated.  */
199   unsigned short negate:1;
200 } metag_addr;
201 
202 /* Linked list of possible parsers for this instruction.  */
203 typedef struct _insn_templates {
204   const insn_template *template;
205   struct _insn_templates *next;
206 } insn_templates;
207 
208 /* Parse an instruction that takes no operands.  */
209 static const char *
parse_none(const char * line,metag_insn * insn,const insn_template * template)210 parse_none (const char *line, metag_insn *insn,
211 	    const insn_template *template)
212 {
213   insn->bits = template->meta_opcode;
214   insn->len = 4;
215   return line;
216 }
217 
218 /* Return the next non-whitespace character in LINE or NULL.  */
219 static const char *
skip_whitespace(const char * line)220 skip_whitespace (const char *line)
221 {
222   const char *l = line;
223 
224   if (is_whitespace_char (*l))
225     {
226       l++;
227     }
228 
229   return l;
230 }
231 
232 /* Return the next non-space character in LINE or NULL.  */
233 static const char *
skip_space(const char * line)234 skip_space (const char *line)
235 {
236   const char *l = line;
237 
238   if (is_space_char (*l))
239     {
240       l++;
241     }
242 
243   return l;
244 }
245 
246 /* Return the character after the current one in LINE if the current
247    character is a comma, otherwise NULL.  */
248 static const char *
skip_comma(const char * line)249 skip_comma (const char *line)
250 {
251   const char *l = line;
252 
253   if (l == NULL || *l != COMMA)
254     return NULL;
255 
256   l++;
257 
258   return l;
259 }
260 
261 /* Return the metag_reg struct corresponding to NAME or NULL if no such
262    register exists.  */
263 static const metag_reg *
parse_gp_reg(const char * name)264 parse_gp_reg (const char *name)
265 {
266   const metag_reg *reg;
267   metag_reg entry;
268 
269   entry.name = name;
270 
271   reg = (const metag_reg *) htab_find (reg_htab, &entry);
272 
273   return reg;
274 }
275 
276 /* Parse a list of up to COUNT GP registers from LINE, returning the
277    registers parsed in REGS and the number parsed in REGS_READ. Return
278    a pointer to the next character or NULL.  */
279 static const char *
parse_gp_regs_list(const char * line,const metag_reg ** regs,size_t count,size_t * regs_read)280 parse_gp_regs_list (const char *line, const metag_reg **regs, size_t count,
281 		    size_t *regs_read)
282 {
283   const char *l = line;
284   char reg_buf[MAX_REG_LEN];
285   int seen_regs = 0;
286   size_t i;
287 
288   for (i = 0; i < count; i++)
289     {
290       size_t len = 0;
291       const char *next;
292 
293       next = l;
294 
295       if (i > 0)
296 	{
297 	  l = skip_comma (l);
298 	  if (l == NULL)
299 	    {
300 	      *regs_read = seen_regs;
301 	      return next;
302 	    }
303 	}
304 
305       while (is_register_char (*l))
306 	{
307 	  reg_buf[len] = *l;
308 	  l++;
309 	  len++;
310 	  if (!(len < MAX_REG_LEN))
311 	    return NULL;
312 	}
313 
314       reg_buf[len] = '\0';
315 
316       if (len)
317 	{
318 	  const metag_reg *reg = parse_gp_reg (reg_buf);
319 
320 	  if (!reg)
321 	    {
322 	      *regs_read = seen_regs;
323 	      return next;
324 	    }
325 	  else
326 	    {
327 	      regs[i] = reg;
328 	      seen_regs++;
329 	    }
330 	}
331       else
332 	{
333 	  *regs_read = seen_regs;
334 	  return next;
335 	}
336     }
337 
338   *regs_read = seen_regs;
339   return l;
340 }
341 
342 /* Parse a list of exactly COUNT GP registers from LINE, returning the
343    registers parsed in REGS. Return a pointer to the next character or NULL.  */
344 static const char *
parse_gp_regs(const char * line,const metag_reg ** regs,size_t count)345 parse_gp_regs (const char *line, const metag_reg **regs, size_t count)
346 {
347   const char *l = line;
348   size_t regs_read = 0;
349 
350   l = parse_gp_regs_list (l, regs, count, &regs_read);
351 
352   if (regs_read != count)
353     return NULL;
354   else
355     return l;
356 }
357 
358 /* Parse a list of exactly COUNT FPU registers from LINE, returning the
359    registers parsed in REGS. Return a pointer to the next character or NULL.  */
360 static const char *
parse_fpu_regs(const char * line,const metag_reg ** regs,size_t count)361 parse_fpu_regs (const char *line, const metag_reg **regs, size_t count)
362 {
363   const char *l = line;
364   size_t regs_read = 0;
365 
366   l = parse_gp_regs_list (l, regs, count, &regs_read);
367 
368   if (regs_read != count)
369     return NULL;
370   else
371     {
372       size_t i;
373       for (i = 0; i < count; i++)
374 	{
375 	  if (regs[i]->unit != UNIT_FX)
376 	    return NULL;
377 	}
378       return l;
379     }
380 }
381 
382 /* Return TRUE if REG1 and REG2 are in paired units.  */
383 static bool
is_unit_pair(const metag_reg * reg1,const metag_reg * reg2)384 is_unit_pair (const metag_reg *reg1, const metag_reg *reg2)
385 {
386   if ((reg1->unit == UNIT_A0 &&
387        (reg2->unit == UNIT_A1)) ||
388       (reg1->unit == UNIT_A1 &&
389        (reg2->unit == UNIT_A0)) ||
390       (reg1->unit == UNIT_D0 &&
391        (reg2->unit == UNIT_D1)) ||
392       (reg1->unit == UNIT_D1 &&
393        (reg2->unit == UNIT_D0)))
394     return true;
395 
396   return false;
397 }
398 
399 /* Return TRUE if REG1 and REG2 form a register pair.  */
400 static bool
is_reg_pair(const metag_reg * reg1,const metag_reg * reg2)401 is_reg_pair (const metag_reg *reg1, const metag_reg *reg2)
402 {
403   if (reg1->unit == UNIT_FX &&
404       reg2->unit == UNIT_FX &&
405       reg2->no == reg1->no + 1)
406     return true;
407 
408   if (reg1->no != reg2->no)
409     return false;
410 
411   return is_unit_pair (reg1, reg2);
412 }
413 
414 /* Parse a pair of GP registers from LINE, returning the registers parsed
415    in REGS. Return a pointer to the next character or NULL.  */
416 static const char *
parse_pair_gp_regs(const char * line,const metag_reg ** regs)417 parse_pair_gp_regs (const char *line, const metag_reg **regs)
418 {
419   const char *l = line;
420 
421   l = parse_gp_regs (line, regs, 2);
422 
423   if (l == NULL)
424     {
425       l = parse_gp_regs (line, regs, 1);
426 
427       if (l == NULL)
428 	return NULL;
429 
430       if (regs[0]->unit == UNIT_RD)
431 	return l;
432       else
433 	return NULL;
434     }
435 
436   if (is_reg_pair (regs[0], regs[1]))
437     return l;
438 
439   return NULL;
440 }
441 
442 /* Parse a unit-to-unit MOV instruction.  */
443 static const char *
parse_mov_u2u(const char * line,metag_insn * insn,const insn_template * template)444 parse_mov_u2u (const char *line, metag_insn *insn,
445 	       const insn_template *template)
446 {
447   const metag_reg *regs[2];
448 
449   line = parse_gp_regs (line, regs, 2);
450 
451   if (line == NULL)
452     return NULL;
453 
454   if (!mfpu_opt && (regs[0]->unit == UNIT_FX || regs[1]->unit == UNIT_FX))
455     {
456       as_bad (_("no floating point unit specified"));
457       return NULL;
458     }
459 
460   insn->bits = (template->meta_opcode |
461 		(regs[1]->no << 19) |
462 		(regs[0]->no << 14) |
463 		(regs[1]->unit << 10) |
464 		(regs[0]->unit << 5));
465   insn->len = 4;
466   return line;
467 }
468 
469 /* Parse a MOV to port instruction.  */
470 static const char *
parse_mov_port(const char * line,metag_insn * insn,const insn_template * template)471 parse_mov_port (const char *line, metag_insn *insn,
472 		const insn_template *template)
473 {
474   const char *l = line;
475   bool is_movl = MINOR_OPCODE (template->meta_opcode) == MOVL_MINOR;
476   const metag_reg *dest_regs[2];
477   const metag_reg *port_regs[1];
478 
479   if (is_movl)
480     l = parse_gp_regs (l, dest_regs, 2);
481   else
482     l = parse_gp_regs (l, dest_regs, 1);
483 
484   if (l == NULL)
485     return NULL;
486 
487   if (template->insn_type == INSN_FPU && dest_regs[0]->unit != UNIT_FX)
488     return NULL;
489 
490   l = skip_comma (l);
491 
492   if (l == NULL ||
493       *l == END_OF_INSN)
494     return NULL;
495 
496   l = parse_gp_regs (l, port_regs, 1);
497 
498   if (l == NULL)
499     return NULL;
500 
501   if (port_regs[0]->unit != UNIT_RD ||
502       port_regs[0]->no != 0)
503     return NULL;
504 
505   if (is_movl)
506     {
507       if (!is_unit_pair (dest_regs[0], dest_regs[1]))
508 	return NULL;
509 
510       insn->bits = (template->meta_opcode |
511 		    (dest_regs[0]->no << 14) |
512 		    (dest_regs[1]->no << 9) |
513 		    ((dest_regs[0]->unit & SHORT_UNIT_MASK) << 5));
514     }
515   else
516     insn->bits = (template->meta_opcode |
517 		  (dest_regs[0]->no << 14) |
518 		  (dest_regs[0]->unit << 5));
519 
520   insn->len = 4;
521   return l;
522 }
523 
524 /* Parse a MOVL to TTREC instruction.  */
525 static const char *
parse_movl_ttrec(const char * line,metag_insn * insn,const insn_template * template)526 parse_movl_ttrec (const char *line, metag_insn *insn,
527 		  const insn_template *template)
528 {
529   const char *l = line;
530   const metag_reg *src_regs[2];
531   const metag_reg *dest_regs[1];
532 
533   l = parse_gp_regs (l, dest_regs, 1);
534 
535   if (l == NULL)
536     return NULL;
537 
538   if (dest_regs[0]->unit != UNIT_TT ||
539       dest_regs[0]->no != 3)
540     return NULL;
541 
542   l = skip_comma (l);
543 
544   if (l == NULL ||
545       *l == END_OF_INSN)
546     return NULL;
547 
548   l = parse_gp_regs (l, src_regs, 2);
549 
550   if (l == NULL)
551     return NULL;
552 
553   if (!is_unit_pair (src_regs[0], src_regs[1]))
554     return NULL;
555 
556   insn->bits = (template->meta_opcode |
557 		(src_regs[0]->no << 19) |
558 		(src_regs[1]->no << 14) |
559 		((src_regs[0]->unit & SHORT_UNIT_MASK) << 7));
560 
561   insn->len = 4;
562   return l;
563 }
564 
565 /* Parse an incrementing or decrementing addressing mode.  */
566 static const char *
parse_addr_incr_op(const char * line,metag_addr * addr)567 parse_addr_incr_op (const char *line, metag_addr *addr)
568 {
569   const char *l = line;
570   const char *ll;
571 
572   ll = l + 1;
573 
574   if (*l == PLUS &&
575       *ll == PLUS)
576     {
577       addr->update = 1;
578       ll++;
579       return ll;
580     }
581   else if (*l == MINUS &&
582 	   *ll == MINUS)
583     {
584       addr->update = 1;
585       addr->negate = 1;
586       ll++;
587       return ll;
588     }
589   return NULL;
590 }
591 
592 /* Parse an pre-incrementing or pre-decrementing addressing mode.  */
593 static const char *
parse_addr_pre_incr_op(const char * line,metag_addr * addr)594 parse_addr_pre_incr_op (const char *line, metag_addr *addr)
595 {
596   return parse_addr_incr_op (line, addr);
597 }
598 
599 /* Parse an post-incrementing or post-decrementing addressing mode.  */
600 static const char *
parse_addr_post_incr_op(const char * line,metag_addr * addr)601 parse_addr_post_incr_op (const char *line, metag_addr *addr)
602 {
603   const char *l;
604 
605   l = parse_addr_incr_op (line, addr);
606 
607   if (l == NULL)
608     return NULL;
609 
610   addr->post_increment = 1;
611 
612   return l;
613 }
614 
615 /* Parse an infix addressing mode.  */
616 static const char *
parse_addr_op(const char * line,metag_addr * addr)617 parse_addr_op (const char *line, metag_addr *addr)
618 {
619   const char *l = line;
620   const char *ll;
621 
622   ll = l + 1;
623 
624   if (*l == PLUS)
625     {
626       if (*ll == PLUS)
627 	{
628 	  addr->update = 1;
629 	  ll++;
630 	  return ll;
631 	}
632       l++;
633       return l;
634     }
635   return NULL;
636 }
637 
638 /* Parse the immediate portion of an addressing mode.  */
639 static const char *
parse_imm_addr(const char * line,metag_addr * addr)640 parse_imm_addr (const char *line, metag_addr *addr)
641 {
642   const char *l = line;
643   char *save_input_line_pointer;
644   expressionS *exp = &addr->exp;
645 
646   /* Skip #.  */
647   if (*l == '#')
648     l++;
649   else
650     return NULL;
651 
652   save_input_line_pointer = input_line_pointer;
653   input_line_pointer = (char *) l;
654 
655   expression (exp);
656 
657   l = input_line_pointer;
658   input_line_pointer = save_input_line_pointer;
659 
660   if (exp->X_op == O_absent || exp->X_op == O_big)
661     {
662       return NULL;
663     }
664   else if (exp->X_op == O_constant)
665     {
666       return l;
667     }
668   else
669     {
670       if (exp->X_op == O_PIC_reloc &&
671 	  exp->X_md == BFD_RELOC_METAG_GETSET_GOT)
672 	{
673 	  exp->X_op = O_symbol;
674 	  addr->reloc_type = BFD_RELOC_METAG_GETSET_GOT;
675 	}
676       else if (exp->X_op == O_PIC_reloc &&
677 	       exp->X_md == BFD_RELOC_METAG_TLS_IE)
678 	{
679 	  exp->X_op = O_symbol;
680 	  addr->reloc_type = BFD_RELOC_METAG_TLS_IE;
681 	}
682       else if (exp->X_op == O_PIC_reloc &&
683 	  exp->X_md == BFD_RELOC_METAG_GOTOFF)
684 	{
685 	  exp->X_op = O_symbol;
686 	  addr->reloc_type = BFD_RELOC_METAG_GETSET_GOTOFF;
687 	}
688       else
689 	addr->reloc_type = BFD_RELOC_METAG_GETSETOFF;
690       return l;
691     }
692 }
693 
694 /* Parse the offset portion of an addressing mode (register or immediate).  */
695 static const char *
parse_addr_offset(const char * line,metag_addr * addr,int size)696 parse_addr_offset (const char *line, metag_addr *addr, int size)
697 {
698   const char *l = line;
699   const metag_reg *regs[1];
700 
701   if (*l == IMM_CHAR)
702     {
703       /* ++ is a valid operator in our addressing but not in an expr. Make
704 	 sure that the expression parser never sees it.  */
705       char *ppp = strstr(l, "++");
706       char ppch = '+';
707 
708       if (ppp)
709 	*ppp = '\0';
710 
711       l = parse_imm_addr (l, addr);
712 
713       if (ppp)
714 	*ppp = ppch;
715 
716       if (l == NULL)
717 	return NULL;
718 
719       if (addr->exp.X_add_number % size)
720 	{
721 	  as_bad (_("offset must be a multiple of %d"), size);
722 	  return NULL;
723 	}
724 
725       addr->immediate = 1;
726       return l;
727     }
728   else
729     {
730       l = parse_gp_regs (l, regs, 1);
731 
732       if (l == NULL)
733 	return NULL;
734 
735       if (regs[0]->unit != addr->base_reg->unit)
736 	{
737 	  as_bad (_("offset and base must be from the same unit"));
738 	  return NULL;
739 	}
740 
741       addr->offset_reg = regs[0];
742       return l;
743     }
744 }
745 
746 /* Parse an addressing mode.  */
747 static const char *
parse_addr(const char * line,metag_addr * addr,unsigned int size)748 parse_addr (const char *line, metag_addr *addr, unsigned int size)
749 {
750   const char *l = line;
751   const char *ll;
752   const metag_reg *regs[1];
753 
754   /* Skip opening square bracket.  */
755   l++;
756 
757   ll = parse_addr_pre_incr_op (l, addr);
758 
759   if (ll != NULL)
760     l = ll;
761 
762   l = parse_gp_regs (l, regs, 1);
763 
764   if (l == NULL)
765     return NULL;
766 
767   addr->base_reg = regs[0];
768 
769   if (*l == ADDR_END_CHAR)
770     {
771       addr->exp.X_op = O_constant;
772       addr->exp.X_add_symbol = NULL;
773       addr->exp.X_op_symbol = NULL;
774       if (addr->update == 1)
775 	{
776 	  /* We have a pre increment/decrement.  */
777 	  addr->exp.X_add_number = size;
778 	}
779       else
780 	{
781 	  /* Simple register with no offset (0 immediate).  */
782 	  addr->exp.X_add_number = 0;
783 	}
784       addr->immediate = 1;
785       l++;
786       return l;
787     }
788 
789   /* We already had a pre increment/decrement.  */
790   if (addr->update == 1)
791     return NULL;
792 
793   ll = parse_addr_post_incr_op (l, addr);
794 
795   if (ll && *ll == ADDR_END_CHAR)
796     {
797       if (addr->update == 1)
798 	{
799 	  /* We have a post increment/decrement.  */
800 	  addr->exp.X_op = O_constant;
801 	  addr->exp.X_add_number = size;
802 	  addr->exp.X_add_symbol = NULL;
803 	  addr->exp.X_op_symbol = NULL;
804 	  addr->post_increment = 1;
805 	}
806       addr->immediate = 1;
807       ll++;
808       return ll;
809     }
810 
811   addr->post_increment = 0;
812 
813   l = parse_addr_op (l, addr);
814 
815   if (l == NULL)
816     return NULL;
817 
818   l = parse_addr_offset (l, addr, size);
819 
820   if (l == NULL)
821     return NULL;
822 
823   if (*l == ADDR_END_CHAR)
824     {
825       l++;
826       return l;
827     }
828 
829   /* We already had a pre increment/decrement. */
830   if (addr->update == 1)
831     return NULL;
832 
833   l = parse_addr_post_incr_op (l, addr);
834 
835   if (l == NULL)
836     return NULL;
837 
838   if (*l == ADDR_END_CHAR)
839     {
840       l++;
841       return l;
842     }
843 
844   return NULL;
845 }
846 
847 /* Parse a GET or pipeline MOV instruction.  */
848 static const char *
parse_get(const char * line,const metag_reg ** regs,metag_addr * addr,unsigned int size,bool is_mov)849 parse_get (const char *line, const metag_reg **regs, metag_addr *addr,
850 	   unsigned int size, bool is_mov)
851 {
852   const char *l = line;
853 
854   if (size == 8)
855     {
856       l = parse_pair_gp_regs (l, regs);
857 
858       if (l == NULL)
859 	  return NULL;
860     }
861   else
862     {
863       l = parse_gp_regs (l, regs, 1);
864 
865       if (l == NULL)
866 	{
867 	  if (!is_mov)
868 	    as_bad (_("invalid destination register"));
869 	  return NULL;
870 	}
871     }
872 
873   l = skip_comma (l);
874 
875   if (l == NULL ||
876       *l == END_OF_INSN)
877     return NULL;
878 
879   l = parse_addr (l, addr, size);
880 
881   if (l == NULL)
882     {
883       if (!is_mov)
884 	as_bad (_("invalid memory operand"));
885       return NULL;
886     }
887 
888   return l;
889 }
890 
891 /* Parse a SET instruction.  */
892 static const char *
parse_set(const char * line,const metag_reg ** regs,metag_addr * addr,unsigned int size)893 parse_set (const char *line, const metag_reg **regs, metag_addr *addr,
894 	   unsigned int size)
895 {
896   const char *l = line;
897 
898   l = parse_addr (l, addr, size);
899 
900   if (l == NULL)
901     {
902 	  as_bad (_("invalid memory operand"));
903 	  return NULL;
904     }
905 
906   l = skip_comma (l);
907 
908   if (l == NULL ||
909       *l == END_OF_INSN)
910     return NULL;
911 
912   if (size == 8)
913     {
914       const char *ll = l;
915 
916       ll = parse_pair_gp_regs (l, regs);
917 
918       if (ll == NULL)
919 	{
920 	  /* Maybe this is an RD register, which is 64 bits wide so needs no
921 	     pair.  */
922 	  l = parse_gp_regs (l, regs, 1);
923 
924 	  if (l == NULL ||
925 	      regs[0]->unit != UNIT_RD)
926 	    {
927 	      return NULL;
928 	    }
929 	}
930       else
931 	l = ll;
932     }
933   else
934     {
935       l = parse_gp_regs (l, regs, 1);
936 
937       if (l == NULL)
938 	{
939 	  as_bad (_("invalid source register"));
940 	  return NULL;
941 	}
942     }
943 
944   return l;
945 }
946 
947 /* Check a signed integer value can be represented in the given number
948    of bits.  */
949 static bool
within_signed_range(int value,unsigned int bits)950 within_signed_range (int value, unsigned int bits)
951 {
952   int min_val = -(1 << (bits - 1));
953   int max_val = (1 << (bits - 1)) - 1;
954   return (value <= max_val) && (value >= min_val);
955 }
956 
957 /* Check an unsigned integer value can be represented in the given number
958    of bits.  */
959 static bool
within_unsigned_range(unsigned int value,unsigned int bits)960 within_unsigned_range (unsigned int value, unsigned int bits)
961 {
962   return value < (unsigned int)(1 << bits);
963 }
964 
965 /* Return TRUE if UNIT can be expressed using a short code.  */
966 static bool
is_short_unit(enum metag_unit unit)967 is_short_unit (enum metag_unit unit)
968 {
969   switch (unit)
970     {
971     case UNIT_A0:
972     case UNIT_A1:
973     case UNIT_D0:
974     case UNIT_D1:
975       return true;
976     default:
977       return false;
978     }
979 }
980 
981 /* Copy reloc data from ADDR to INSN.  */
982 static void
copy_addr_reloc(metag_insn * insn,metag_addr * addr)983 copy_addr_reloc (metag_insn *insn, metag_addr *addr)
984 {
985   memcpy (&insn->reloc_exp, &addr->exp, sizeof(insn->reloc_exp));
986   insn->reloc_type = addr->reloc_type;
987 }
988 
989 /* Parse a GET, SET or pipeline MOV instruction.  */
990 static const char *
parse_get_set(const char * line,metag_insn * insn,const insn_template * template)991 parse_get_set (const char *line, metag_insn *insn,
992 	       const insn_template *template)
993 {
994   const char *l = line;
995   const metag_reg *regs[2];
996   metag_addr addr;
997   unsigned int size = metag_get_set_size_bytes (template->meta_opcode);
998   bool is_get = MAJOR_OPCODE (template->meta_opcode) == OPC_GET;
999   unsigned int reg_no;
1000 
1001   memset(&addr, 0, sizeof(addr));
1002   addr.reloc_type = BFD_RELOC_UNUSED;
1003 
1004   if (is_get)
1005     {
1006       bool is_mov = startswith (template->name, "MOV");
1007 
1008       l = parse_get (l, regs, &addr, size, is_mov);
1009 
1010       if (l == NULL)
1011 	return NULL;
1012 
1013       if (!(regs[0]->unit == UNIT_D0 ||
1014 	    regs[0]->unit == UNIT_D1 ||
1015 	    regs[0]->unit == UNIT_A0 ||
1016 	    regs[0]->unit == UNIT_A1 ||
1017 	    (regs[0]->unit == UNIT_RD && is_mov) ||
1018 	    (regs[0]->unit == UNIT_CT && size == 4) ||
1019 	    (regs[0]->unit == UNIT_PC && size == 4) ||
1020 	    (regs[0]->unit == UNIT_TR && size == 4) ||
1021 	    (regs[0]->unit == UNIT_TT && (size == 4 || size == 8)) ||
1022 	    regs[0]->unit == UNIT_FX))
1023 	{
1024 	  as_bad (_("invalid destination unit"));
1025 	  return NULL;
1026 	}
1027 
1028       if (regs[0]->unit == UNIT_RD)
1029 	{
1030 	  if (regs[0]->no == 0)
1031 	    {
1032 	      as_bad (_("mov cannot use RD port as destination"));
1033 	      return NULL;
1034 	    }
1035 	}
1036 
1037       reg_no = regs[0]->no;
1038     }
1039   else
1040     {
1041       l = parse_set (l, regs, &addr, size);
1042 
1043       if (l == NULL)
1044 	return NULL;
1045 
1046       if (!(regs[0]->unit == UNIT_D0 ||
1047 	    regs[0]->unit == UNIT_D1 ||
1048 	    regs[0]->unit == UNIT_A0 ||
1049 	    regs[0]->unit == UNIT_A1 ||
1050 	    regs[0]->unit == UNIT_RD ||
1051 	    (regs[0]->unit == UNIT_CT && size == 4) ||
1052 	    (regs[0]->unit == UNIT_PC && size == 4) ||
1053 	    (regs[0]->unit == UNIT_TR && size == 4) ||
1054 	    (regs[0]->unit == UNIT_TT && (size == 4 || size == 8)) ||
1055 	    regs[0]->unit == UNIT_FX))
1056 	{
1057 	  as_bad (_("invalid source unit"));
1058 	  return NULL;
1059 	}
1060 
1061       if (addr.immediate == 0 &&
1062 	  (regs[0]->unit == addr.base_reg->unit ||
1063 	   (size == 8 && is_unit_pair (regs[0], addr.base_reg))))
1064 	{
1065 	  as_bad (_("source and address units must not be shared for this addressing mode"));
1066 	  return NULL;
1067 	}
1068 
1069       if (regs[0]->unit == UNIT_RD)
1070 	{
1071 	  if (regs[0]->no != 0)
1072 	    {
1073 	      as_bad (_("set can only use RD port as source"));
1074 	      return NULL;
1075 	    }
1076 	  reg_no = 16;
1077 	}
1078       else
1079 	reg_no = regs[0]->no;
1080     }
1081 
1082   insn->bits = (template->meta_opcode |
1083 		(reg_no << 19) |
1084 		(regs[0]->unit << 1));
1085 
1086   if (!is_short_unit (addr.base_reg->unit))
1087     {
1088       as_bad (_("base unit must be one of %s"), SHORT_UNITS);
1089       return NULL;
1090     }
1091 
1092   insn->bits |= ((addr.base_reg->no << 14) |
1093 		 ((addr.base_reg->unit & SHORT_UNIT_MASK) << 5));
1094 
1095   if (addr.immediate)
1096     {
1097       int offset = addr.exp.X_add_number;
1098 
1099       copy_addr_reloc (insn, &addr);
1100 
1101       if (addr.negate)
1102 	offset = -offset;
1103 
1104       offset = offset / (int)size;
1105 
1106       if (!within_signed_range (offset, GET_SET_IMM_BITS))
1107 	{
1108 	  /* We already tried to encode as an extended GET/SET.  */
1109 	  as_bad (_("offset value out of range"));
1110 	  return NULL;
1111 	}
1112 
1113       offset = offset & GET_SET_IMM_MASK;
1114 
1115       insn->bits |= (0x1 << 25);
1116       insn->bits |= (offset << 8);
1117     }
1118   else
1119     {
1120       insn->bits |= (addr.offset_reg->no << 9);
1121     }
1122 
1123   if (addr.update)
1124     insn->bits |= (0x1 << 7);
1125 
1126   if (addr.post_increment)
1127     insn->bits |= 0x1;
1128 
1129   insn->len = 4;
1130   return l;
1131 }
1132 
1133 /* Parse an extended GET or SET instruction.  */
1134 static const char *
parse_get_set_ext(const char * line,metag_insn * insn,const insn_template * template)1135 parse_get_set_ext (const char *line, metag_insn *insn,
1136 		   const insn_template *template)
1137 {
1138   const char *l = line;
1139   const metag_reg *regs[2];
1140   metag_addr addr;
1141   unsigned int size = metag_get_set_ext_size_bytes (template->meta_opcode);
1142   bool is_get = MINOR_OPCODE (template->meta_opcode) == GET_EXT_MINOR;
1143   bool is_mov = MINOR_OPCODE (template->meta_opcode) == MOV_EXT_MINOR;
1144   unsigned int reg_unit;
1145 
1146   memset(&addr, 0, sizeof(addr));
1147   addr.reloc_type = BFD_RELOC_UNUSED;
1148 
1149   if (is_get || is_mov)
1150     {
1151       l = parse_get (l, regs, &addr, size, is_mov);
1152     }
1153   else
1154     {
1155       l = parse_set (l, regs, &addr, size);
1156     }
1157 
1158   if (l == NULL)
1159     return NULL;
1160 
1161   /* Extended GET/SET does not support incrementing addressing.  */
1162   if (addr.update)
1163     return NULL;
1164 
1165   if (is_mov)
1166     {
1167       if (regs[0]->unit != UNIT_RD)
1168 	{
1169 	  as_bad (_("destination unit must be RD"));
1170 	  return NULL;
1171 	}
1172       reg_unit = 0;
1173     }
1174   else
1175     {
1176       if (!is_short_unit (regs[0]->unit))
1177 	{
1178 	  return NULL;
1179 	}
1180       reg_unit = regs[0]->unit;
1181     }
1182 
1183   insn->bits = (template->meta_opcode |
1184 		(regs[0]->no << 19) |
1185 		((reg_unit & SHORT_UNIT_MASK) << 3));
1186 
1187   if (!is_short_unit (addr.base_reg->unit))
1188     {
1189       as_bad (_("base unit must be one of %s"), SHORT_UNITS);
1190       return NULL;
1191     }
1192 
1193   if (addr.base_reg->no > 1)
1194     {
1195       return NULL;
1196     }
1197 
1198   insn->bits |= ((addr.base_reg->no & EXT_BASE_REG_MASK) |
1199 		 ((addr.base_reg->unit & SHORT_UNIT_MASK) << 5));
1200 
1201   if (addr.immediate)
1202     {
1203       int offset = addr.exp.X_add_number;
1204 
1205       copy_addr_reloc (insn, &addr);
1206 
1207       if (addr.negate)
1208 	offset = -offset;
1209 
1210       offset = offset / (int)size;
1211 
1212       if (!within_signed_range (offset, GET_SET_EXT_IMM_BITS))
1213 	{
1214 	  /* Parsing as a standard GET/SET provides a smaller offset.  */
1215 	  as_bad (_("offset value out of range"));
1216 	  return NULL;
1217 	}
1218 
1219       offset = offset & GET_SET_EXT_IMM_MASK;
1220 
1221       insn->bits |= (offset << 7);
1222     }
1223   else
1224     {
1225       return NULL;
1226     }
1227 
1228   insn->len = 4;
1229   return l;
1230 }
1231 
1232 /* Parse an MGET or MSET instruction addressing mode.  */
1233 static const char *
parse_mget_mset_addr(const char * line,metag_addr * addr)1234 parse_mget_mset_addr (const char *line, metag_addr *addr)
1235 {
1236   const char *l = line;
1237   const char *ll;
1238   const metag_reg *regs[1];
1239 
1240   /* Skip opening square bracket.  */
1241   l++;
1242 
1243   l = parse_gp_regs (l, regs, 1);
1244 
1245   if (l == NULL)
1246     return NULL;
1247 
1248   addr->base_reg = regs[0];
1249 
1250   ll = parse_addr_post_incr_op (l, addr);
1251 
1252   if (ll != NULL)
1253     l = ll;
1254 
1255   if (addr->negate == 1)
1256     return NULL;
1257 
1258   if (*l == ADDR_END_CHAR)
1259     {
1260       l++;
1261       return l;
1262     }
1263 
1264   return NULL;
1265 }
1266 
1267 /* Parse an MGET instruction.  */
1268 static const char *
parse_mget(const char * line,const metag_reg ** regs,metag_addr * addr,size_t * regs_read)1269 parse_mget (const char *line, const metag_reg **regs, metag_addr *addr,
1270 	    size_t *regs_read)
1271 {
1272   const char *l = line;
1273 
1274   l = parse_gp_regs_list (l, regs, MGET_MSET_MAX_REGS, regs_read);
1275 
1276   if (l == NULL ||
1277       *regs_read == 0)
1278     {
1279       as_bad (_("invalid destination register list"));
1280       return NULL;
1281     }
1282 
1283   l = skip_comma (l);
1284 
1285   if (l == NULL ||
1286       *l == END_OF_INSN)
1287     return NULL;
1288 
1289   l = parse_mget_mset_addr (l, addr);
1290 
1291   if (l == NULL)
1292     {
1293 	  as_bad (_("invalid memory operand"));
1294 	  return NULL;
1295     }
1296 
1297   return l;
1298 }
1299 
1300 /* Parse an MSET instruction.  */
1301 static const char *
parse_mset(const char * line,const metag_reg ** regs,metag_addr * addr,size_t * regs_read)1302 parse_mset (const char *line, const metag_reg **regs, metag_addr *addr,
1303 	    size_t *regs_read)
1304 {
1305   const char *l = line;
1306 
1307   l = parse_mget_mset_addr (l, addr);
1308 
1309   if (l == NULL)
1310     {
1311 	  as_bad (_("invalid memory operand"));
1312 	  return NULL;
1313     }
1314 
1315   l = skip_comma (l);
1316 
1317   if (l == NULL ||
1318       *l == END_OF_INSN)
1319     return NULL;
1320 
1321   l = parse_gp_regs_list (l, regs, MGET_MSET_MAX_REGS, regs_read);
1322 
1323   if (l == NULL ||
1324       *regs_read == 0)
1325     {
1326       as_bad (_("invalid source register list"));
1327       return NULL;
1328     }
1329 
1330   return l;
1331 }
1332 
1333 /* Take a register list REGS of size REGS_READ and convert it into an
1334    rmask value if possible. Return the rmask value in RMASK and the
1335    lowest numbered register in LOWEST_REG. Return TRUE if the conversion
1336    was successful.  */
1337 static bool
check_rmask(const metag_reg ** regs,size_t regs_read,bool is_fpu,bool is_64bit,unsigned int * lowest_reg,unsigned int * rmask)1338 check_rmask (const metag_reg **regs, size_t regs_read, bool is_fpu,
1339 	     bool is_64bit, unsigned int *lowest_reg,
1340 	     unsigned int *rmask)
1341 {
1342   unsigned int reg_unit = regs[0]->unit;
1343   size_t i;
1344 
1345   for (i = 0; i < regs_read; i++)
1346     {
1347       if (is_fpu)
1348 	{
1349 	  if (is_64bit && regs[i]->no % 2)
1350 	    {
1351 	      as_bad (_("register list must be even numbered"));
1352 	      return false;
1353 	    }
1354 	}
1355       else if (regs[i]->unit != reg_unit)
1356 	{
1357 	  as_bad (_("register list must be from the same unit"));
1358 	  return false;
1359 	}
1360 
1361       if (regs[i]->no < *lowest_reg)
1362 	*lowest_reg = regs[i]->no;
1363     }
1364 
1365   for (i = 0; i < regs_read; i++)
1366     {
1367       unsigned int next_bit, next_reg;
1368       if (regs[i]->no == *lowest_reg)
1369 	continue;
1370 
1371       if (is_fpu && is_64bit)
1372 	next_reg = ((regs[i]->no / 2) - ((*lowest_reg / 2) + 1));
1373       else
1374 	next_reg = (regs[i]->no - (*lowest_reg + 1));
1375 
1376       next_bit = (1 << next_reg);
1377 
1378       if (*rmask & next_bit)
1379 	{
1380 	  as_bad (_("register list must not contain duplicates"));
1381 	  return false;
1382 	}
1383 
1384       *rmask |= next_bit;
1385     }
1386 
1387   return true;
1388 }
1389 
1390 /* Parse an MGET or MSET instruction.  */
1391 static const char *
parse_mget_mset(const char * line,metag_insn * insn,const insn_template * template)1392 parse_mget_mset (const char *line, metag_insn *insn,
1393 		 const insn_template *template)
1394 {
1395   const char *l = line;
1396   const metag_reg *regs[MGET_MSET_MAX_REGS];
1397   metag_addr addr;
1398   bool is_get = MAJOR_OPCODE (template->meta_opcode) == OPC_GET;
1399   bool is_fpu = (MINOR_OPCODE (template->meta_opcode) & 0x6) == 0x6;
1400   bool is_64bit = (MINOR_OPCODE (template->meta_opcode) & 0x1) == 0x1;
1401   size_t regs_read = 0;
1402   unsigned int rmask = 0, reg_unit = 0, lowest_reg = 0xffffffff;
1403 
1404   memset(&addr, 0, sizeof(addr));
1405   addr.reloc_type = BFD_RELOC_UNUSED;
1406 
1407   if (is_get)
1408     {
1409       l = parse_mget (l, regs, &addr, &regs_read);
1410     }
1411   else
1412     {
1413       l = parse_mset (l, regs, &addr, &regs_read);
1414     }
1415 
1416   if (l == NULL)
1417     return NULL;
1418 
1419   if (!check_rmask (regs, regs_read, is_fpu, is_64bit, &lowest_reg, &rmask))
1420     return NULL;
1421 
1422   reg_unit = regs[0]->unit;
1423 
1424   if (is_fpu)
1425     {
1426       if (reg_unit != UNIT_FX)
1427 	return NULL;
1428 
1429       reg_unit = 0;
1430     }
1431   else if (reg_unit == UNIT_FX)
1432     return NULL;
1433 
1434   insn->bits = (template->meta_opcode |
1435 		(lowest_reg << 19) |
1436 		((reg_unit & SHORT_UNIT_MASK) << 3));
1437 
1438   if (!is_short_unit (addr.base_reg->unit))
1439     {
1440       as_bad (_("base unit must be one of %s"), SHORT_UNITS);
1441       return NULL;
1442     }
1443 
1444   insn->bits |= ((addr.base_reg->no << 14) |
1445 		 ((addr.base_reg->unit & SHORT_UNIT_MASK) << 5));
1446 
1447   insn->bits |= (rmask & RMASK_MASK) << 7;
1448 
1449   insn->len = 4;
1450   return l;
1451 }
1452 
1453 /* Parse a list of registers for MMOV pipeline prime.  */
1454 static const char *
parse_mmov_prime_list(const char * line,const metag_reg ** regs,unsigned int * rmask)1455 parse_mmov_prime_list (const char *line, const metag_reg **regs,
1456 		       unsigned int *rmask)
1457 {
1458   const char *l = line;
1459   const metag_reg *ra_regs[MMOV_MAX_REGS];
1460   size_t regs_read = 0, i;
1461   unsigned int mask = 0;
1462 
1463   l = parse_gp_regs_list (l, regs, 1, &regs_read);
1464 
1465   /* First register must be a port. */
1466   if (l == NULL || regs[0]->unit != UNIT_RD)
1467     return NULL;
1468 
1469   l = skip_comma (l);
1470 
1471   if (l == NULL)
1472     return NULL;
1473 
1474   l = parse_gp_regs_list (l, ra_regs, MMOV_MAX_REGS, &regs_read);
1475 
1476   if (l == NULL)
1477     return NULL;
1478 
1479   /* Check remaining registers match the first.
1480 
1481      Note that we also accept RA (0x10) as input for the remaining registers.
1482      Whilst this doesn't represent the instruction in any way we're stuck
1483      with it because the embedded assembler accepts it.  */
1484   for (i = 0; i < regs_read; i++)
1485     {
1486       if (ra_regs[i]->unit != UNIT_RD ||
1487 	  (ra_regs[i]->no != 0x10 && ra_regs[i]->no != regs[0]->no))
1488 	return NULL;
1489 
1490       mask = (mask << 1) | 0x1;
1491     }
1492 
1493   *rmask = mask;
1494 
1495   return l;
1496 }
1497 
1498 /* Parse a MMOV instruction.  */
1499 static const char *
parse_mmov(const char * line,metag_insn * insn,const insn_template * template)1500 parse_mmov (const char *line, metag_insn *insn,
1501 	    const insn_template *template)
1502 {
1503   const char *l = line;
1504   bool is_fpu = template->insn_type == INSN_FPU;
1505   bool is_prime = (MINOR_OPCODE (template->meta_opcode) & 0x2) != 0 && !is_fpu;
1506   bool is_64bit = (MINOR_OPCODE (template->meta_opcode) & 0x1) != 0;
1507   unsigned int rmask = 0;
1508 
1509   if (is_prime)
1510     {
1511       const metag_reg *reg;
1512       metag_addr addr;
1513 
1514       memset (&addr, 0, sizeof(addr));
1515 
1516       l = parse_mmov_prime_list (l, &reg, &rmask);
1517 
1518       if (l == NULL)
1519 	return NULL;
1520 
1521       l = skip_comma (l);
1522 
1523       if (l == NULL)
1524 	return NULL;
1525 
1526       l = parse_mget_mset_addr (l, &addr);
1527 
1528       if (l == NULL)
1529 	{
1530 	  as_bad (_("invalid memory operand"));
1531 	  return NULL;
1532 	}
1533 
1534       insn->bits = (template->meta_opcode |
1535 		    (reg->no << 19) |
1536 		    (addr.base_reg->no << 14) |
1537 		    ((rmask & RMASK_MASK) << 7) |
1538 		    ((addr.base_reg->unit & SHORT_UNIT_MASK) << 5));
1539     }
1540   else
1541     {
1542       const metag_reg *regs[MMOV_MAX_REGS + 1];
1543       unsigned int lowest_reg = 0xffffffff;
1544       size_t regs_read = 0;
1545 
1546       l = parse_gp_regs_list (l, regs, MMOV_MAX_REGS + 1, &regs_read);
1547 
1548       if (l == NULL || regs_read == 0)
1549 	return NULL;
1550 
1551       if (!is_short_unit (regs[0]->unit) &&
1552 	  !(is_fpu && regs[0]->unit == UNIT_FX))
1553 	{
1554 	  return NULL;
1555 	}
1556 
1557       if (!(regs[regs_read-1]->unit == UNIT_RD &&
1558 	    regs[regs_read-1]->no == 0))
1559 	{
1560 	  return NULL;
1561 	}
1562 
1563       if (!check_rmask (regs, regs_read - 1, is_fpu, is_64bit, &lowest_reg,
1564 			&rmask))
1565 	return NULL;
1566 
1567       if (is_fpu)
1568 	{
1569 	  insn->bits = (template->meta_opcode |
1570 			(regs[0]->no << 14) |
1571 			((rmask & RMASK_MASK) << 7));
1572 	}
1573       else
1574 	{
1575 	  insn->bits = (template->meta_opcode |
1576 			(regs[0]->no << 19) |
1577 			((rmask & RMASK_MASK) << 7) |
1578 			((regs[0]->unit & SHORT_UNIT_MASK) << 3));
1579 	}
1580     }
1581 
1582   insn->len = 4;
1583   return l;
1584 }
1585 
1586 /* Parse an immediate constant.  */
1587 static const char *
parse_imm_constant(const char * line,metag_insn * insn,int * value)1588 parse_imm_constant (const char *line, metag_insn *insn, int *value)
1589 {
1590   const char *l = line;
1591   char *save_input_line_pointer;
1592   expressionS *exp = &insn->reloc_exp;
1593 
1594   /* Skip #. */
1595   if (*l == '#')
1596     l++;
1597   else
1598     return NULL;
1599 
1600   save_input_line_pointer = input_line_pointer;
1601   input_line_pointer = (char *) l;
1602 
1603   expression (exp);
1604 
1605   l = input_line_pointer;
1606   input_line_pointer = save_input_line_pointer;
1607 
1608   if (exp->X_op == O_constant)
1609     {
1610       *value = exp->X_add_number;
1611 
1612       return l;
1613     }
1614   else
1615     {
1616       return NULL;
1617     }
1618 }
1619 
1620 /* Parse an MDRD instruction.  */
1621 static const char *
parse_mdrd(const char * line,metag_insn * insn,const insn_template * template)1622 parse_mdrd (const char *line, metag_insn *insn,
1623 	    const insn_template *template)
1624 {
1625   const char *l = line;
1626   unsigned int rmask = 0;
1627   int value = 0, i;
1628 
1629   l = parse_imm_constant (l, insn, &value);
1630 
1631   if (l == NULL)
1632     return NULL;
1633 
1634   if (value < 1 || value > 8)
1635     {
1636       as_bad (_("MDRD value must be between 1 and 8"));
1637       return NULL;
1638     }
1639 
1640   for (i = 1; i < value; i++)
1641     {
1642       rmask <<= 1;
1643       rmask |= 1;
1644     }
1645 
1646   insn->bits = (template->meta_opcode |
1647 		(rmask << 7));
1648 
1649   insn->len = 4;
1650   return l;
1651 }
1652 
1653 /* Parse a conditional SET instruction.  */
1654 static const char *
parse_cond_set(const char * line,metag_insn * insn,const insn_template * template)1655 parse_cond_set (const char *line, metag_insn *insn,
1656 		const insn_template *template)
1657 {
1658   const char *l = line;
1659   const metag_reg *regs[2];
1660   metag_addr addr;
1661   unsigned int size = metag_cond_set_size_bytes (template->meta_opcode);
1662   unsigned int reg_no;
1663 
1664   memset(&addr, 0, sizeof(addr));
1665   addr.reloc_type = BFD_RELOC_UNUSED;
1666 
1667   l = parse_set (l, regs, &addr, size);
1668 
1669   if (l == NULL)
1670     return NULL;
1671 
1672   if (regs[0]->unit == UNIT_RD)
1673     {
1674       if (regs[0]->no != 0)
1675 	{
1676 	  as_bad (_("set can only use RD port as source"));
1677 	  return NULL;
1678 	}
1679       reg_no = 16;
1680     }
1681   else
1682     reg_no = regs[0]->no;
1683 
1684   if (addr.update)
1685     return NULL;
1686 
1687   if (!(addr.immediate &&
1688 	addr.exp.X_add_number == 0))
1689     return NULL;
1690 
1691   insn->bits = (template->meta_opcode |
1692 		(reg_no << 19) |
1693 		(regs[0]->unit << 10));
1694 
1695   if (!is_short_unit (addr.base_reg->unit))
1696     {
1697       as_bad (_("base unit must be one of %s"), SHORT_UNITS);
1698       return NULL;
1699     }
1700 
1701   insn->bits |= ((addr.base_reg->no << 14) |
1702 		 ((addr.base_reg->unit & SHORT_UNIT_MASK) << 5));
1703 
1704   insn->len = 4;
1705   return l;
1706 }
1707 
1708 /* Parse an XFR instruction.  */
1709 static const char *
parse_xfr(const char * line,metag_insn * insn,const insn_template * template)1710 parse_xfr (const char *line, metag_insn *insn,
1711 	   const insn_template *template)
1712 {
1713   const char *l = line;
1714   metag_addr dest_addr, src_addr;
1715   unsigned int size = 4;
1716 
1717   memset(&dest_addr, 0, sizeof(dest_addr));
1718   memset(&src_addr, 0, sizeof(src_addr));
1719   dest_addr.reloc_type = BFD_RELOC_UNUSED;
1720   src_addr.reloc_type = BFD_RELOC_UNUSED;
1721 
1722   l = parse_addr (l, &dest_addr, size);
1723 
1724   if (l == NULL ||
1725       dest_addr.immediate == 1)
1726     {
1727 	  as_bad (_("invalid destination memory operand"));
1728 	  return NULL;
1729     }
1730 
1731   l = skip_comma (l);
1732 
1733   if (l == NULL ||
1734       *l == END_OF_INSN)
1735     return NULL;
1736 
1737   l = parse_addr (l, &src_addr, size);
1738 
1739   if (l == NULL ||
1740       src_addr.immediate == 1)
1741     {
1742 	  as_bad (_("invalid source memory operand"));
1743 	  return NULL;
1744     }
1745 
1746   if (!is_short_unit (dest_addr.base_reg->unit) ||
1747       !is_short_unit (src_addr.base_reg->unit))
1748     {
1749       as_bad (_("address units must be one of %s"), SHORT_UNITS);
1750       return NULL;
1751     }
1752 
1753   if ((dest_addr.base_reg->unit != dest_addr.offset_reg->unit) ||
1754       (src_addr.base_reg->unit != src_addr.offset_reg->unit))
1755     {
1756       as_bad (_("base and offset must be from the same unit"));
1757       return NULL;
1758     }
1759 
1760   if (dest_addr.update == 1 &&
1761       src_addr.update == 1 &&
1762       dest_addr.post_increment != src_addr.post_increment)
1763     {
1764       as_bad (_("source and destination increment mode must agree"));
1765       return NULL;
1766     }
1767 
1768   insn->bits = (template->meta_opcode |
1769 		(src_addr.base_reg->no << 19) |
1770 		(src_addr.offset_reg->no << 14) |
1771 		((src_addr.base_reg->unit & SHORT_UNIT_MASK) << 2));
1772 
1773   insn->bits |= ((dest_addr.base_reg->no << 9) |
1774 		 (dest_addr.offset_reg->no << 4) |
1775 		 ((dest_addr.base_reg->unit & SHORT_UNIT_MASK)));
1776 
1777   if (dest_addr.update == 1)
1778     insn->bits |= (1 << 26);
1779 
1780   if (src_addr.update == 1)
1781     insn->bits |= (1 << 27);
1782 
1783   if (dest_addr.post_increment == 1 ||
1784       src_addr.post_increment == 1)
1785     insn->bits |= (1 << 24);
1786 
1787   insn->len = 4;
1788   return l;
1789 }
1790 
1791 /* Parse an 8bit immediate value.  */
1792 static const char *
parse_imm8(const char * line,metag_insn * insn,int * value)1793 parse_imm8 (const char *line, metag_insn *insn, int *value)
1794 {
1795   const char *l = line;
1796   char *save_input_line_pointer;
1797   expressionS *exp = &insn->reloc_exp;
1798 
1799   /* Skip #. */
1800   if (*l == '#')
1801     l++;
1802   else
1803     return NULL;
1804 
1805   save_input_line_pointer = input_line_pointer;
1806   input_line_pointer = (char *) l;
1807 
1808   expression (exp);
1809 
1810   l = input_line_pointer;
1811   input_line_pointer = save_input_line_pointer;
1812 
1813   if (exp->X_op == O_absent || exp->X_op == O_big)
1814     {
1815       return NULL;
1816     }
1817   else if (exp->X_op == O_constant)
1818     {
1819       *value = exp->X_add_number;
1820     }
1821   else
1822     {
1823       insn->reloc_type = BFD_RELOC_METAG_REL8;
1824       insn->reloc_pcrel = 0;
1825     }
1826 
1827   return l;
1828 }
1829 
1830 /* Parse a 16bit immediate value.  */
1831 static const char *
parse_imm16(const char * line,metag_insn * insn,int * value)1832 parse_imm16 (const char *line, metag_insn *insn, int *value)
1833 {
1834   const char *l = line;
1835   char *save_input_line_pointer;
1836   expressionS *exp = &insn->reloc_exp;
1837   bool is_hi = false;
1838   bool is_lo = false;
1839 
1840   /* Skip #. */
1841   if (*l == '#')
1842     l++;
1843   else
1844     return NULL;
1845 
1846   if (strncasecmp (l, "HI", 2) == 0)
1847     {
1848       is_hi = true;
1849       l += 2;
1850     }
1851   else if (strncasecmp (l, "LO", 2) == 0)
1852     {
1853       is_lo = true;
1854       l += 2;
1855     }
1856 
1857   save_input_line_pointer = input_line_pointer;
1858   input_line_pointer = (char *) l;
1859 
1860   expression (exp);
1861 
1862   l = input_line_pointer;
1863   input_line_pointer = save_input_line_pointer;
1864 
1865   if (exp->X_op == O_absent || exp->X_op == O_big)
1866     {
1867       return NULL;
1868     }
1869   else if (exp->X_op == O_constant)
1870     {
1871       if (is_hi)
1872 	*value = (exp->X_add_number >> 16) & IMM16_MASK;
1873       else if (is_lo)
1874 	*value = exp->X_add_number & IMM16_MASK;
1875       else
1876 	*value = exp->X_add_number;
1877     }
1878   else
1879     {
1880       if (exp->X_op == O_PIC_reloc)
1881 	{
1882 	  exp->X_op = O_symbol;
1883 
1884 	  if (exp->X_md == BFD_RELOC_METAG_GOTOFF)
1885 	    {
1886 	      if (is_hi)
1887 		insn->reloc_type = BFD_RELOC_METAG_HI16_GOTOFF;
1888 	      else if (is_lo)
1889 		insn->reloc_type = BFD_RELOC_METAG_LO16_GOTOFF;
1890 	      else
1891 		return NULL;
1892 	    }
1893 	  else if (exp->X_md == BFD_RELOC_METAG_PLT)
1894 	    {
1895 	      if (is_hi)
1896 		insn->reloc_type = BFD_RELOC_METAG_HI16_PLT;
1897 	      else if (is_lo)
1898 		insn->reloc_type = BFD_RELOC_METAG_LO16_PLT;
1899 	      else
1900 		return NULL;
1901 	    }
1902 	  else if (exp->X_md == BFD_RELOC_METAG_TLS_LDO)
1903 	    {
1904 	      if (is_hi)
1905 		insn->reloc_type = BFD_RELOC_METAG_TLS_LDO_HI16;
1906 	      else if (is_lo)
1907 		insn->reloc_type = BFD_RELOC_METAG_TLS_LDO_LO16;
1908 	      else
1909 		return NULL;
1910 	    }
1911 	  else if (exp->X_md == BFD_RELOC_METAG_TLS_IENONPIC)
1912 	    {
1913 	      if (is_hi)
1914 		insn->reloc_type = BFD_RELOC_METAG_TLS_IENONPIC_HI16;
1915 	      else if (is_lo)
1916 		insn->reloc_type = BFD_RELOC_METAG_TLS_IENONPIC_LO16;
1917 	      else
1918 		return NULL;
1919 	    }
1920 	  else if (exp->X_md == BFD_RELOC_METAG_TLS_LE)
1921 	    {
1922 	      if (is_hi)
1923 		insn->reloc_type = BFD_RELOC_METAG_TLS_LE_HI16;
1924 	      else if (is_lo)
1925 		insn->reloc_type = BFD_RELOC_METAG_TLS_LE_LO16;
1926 	      else
1927 		return NULL;
1928 	    }
1929 	  else if (exp->X_md == BFD_RELOC_METAG_TLS_GD ||
1930 		   exp->X_md == BFD_RELOC_METAG_TLS_LDM)
1931 	    insn->reloc_type = exp->X_md;
1932 	}
1933       else
1934 	{
1935 	  if (exp->X_op == O_symbol && exp->X_add_symbol == GOT_symbol)
1936 	    {
1937 	      if (is_hi)
1938 		insn->reloc_type = BFD_RELOC_METAG_HI16_GOTPC;
1939 	      else if (is_lo)
1940 		insn->reloc_type = BFD_RELOC_METAG_LO16_GOTPC;
1941 	      else
1942 		return NULL;
1943 	    }
1944 	  else
1945 	    {
1946 	      if (is_hi)
1947 		insn->reloc_type = BFD_RELOC_METAG_HIADDR16;
1948 	      else if (is_lo)
1949 		insn->reloc_type = BFD_RELOC_METAG_LOADDR16;
1950 	      else
1951 		insn->reloc_type = BFD_RELOC_METAG_REL16;
1952 	    }
1953 	}
1954 
1955       insn->reloc_pcrel = 0;
1956     }
1957 
1958   return l;
1959 }
1960 
1961 /* Parse a MOV to control unit instruction.  */
1962 static const char *
parse_mov_ct(const char * line,metag_insn * insn,const insn_template * template)1963 parse_mov_ct (const char *line, metag_insn *insn,
1964 	      const insn_template *template)
1965 {
1966   const char *l = line;
1967   const metag_reg *regs[1];
1968   bool top = (template->meta_opcode & 0x1) != 0;
1969   bool is_trace = ((template->meta_opcode >> 2) & 0x1) != 0;
1970   bool sign_extend = 0;
1971   int value = 0;
1972 
1973   l = parse_gp_regs (l, regs, 1);
1974 
1975   if (l == NULL)
1976     return NULL;
1977 
1978   if (is_trace)
1979     {
1980       if (regs[0]->unit != UNIT_TT)
1981 	return NULL;
1982     }
1983   else
1984     {
1985       if (regs[0]->unit != UNIT_CT)
1986 	return NULL;
1987     }
1988 
1989   l = skip_comma (l);
1990 
1991   if (l == NULL ||
1992       *l == END_OF_INSN)
1993     return NULL;
1994 
1995   l = parse_imm16 (l, insn, &value);
1996 
1997   if (l == NULL)
1998     return NULL;
1999 
2000   if (value < 0)
2001     sign_extend = 1;
2002 
2003   insn->bits = (template->meta_opcode |
2004 		(regs[0]->no << 19) |
2005 		((value & IMM16_MASK) << 3));
2006 
2007   if (sign_extend && !top)
2008     insn->bits |= (1 << 1);
2009 
2010   insn->len = 4;
2011   return l;
2012 }
2013 
2014 /* Parse a SWAP instruction.  */
2015 static const char *
parse_swap(const char * line,metag_insn * insn,const insn_template * template)2016 parse_swap (const char *line, metag_insn *insn,
2017 	    const insn_template *template)
2018 {
2019   const char *l = line;
2020   const metag_reg *regs[2];
2021 
2022   l = parse_gp_regs (l, regs, 2);
2023 
2024   if (l == NULL)
2025     return NULL;
2026 
2027   /* PC.r | CT.r | TR.r | TT.r are treated as if they are a single unit.  */
2028   switch (regs[0]->unit)
2029     {
2030     case UNIT_PC:
2031     case UNIT_CT:
2032     case UNIT_TR:
2033     case UNIT_TT:
2034       if (regs[1]->unit == UNIT_PC
2035 	  || regs[1]->unit == UNIT_CT
2036 	  || regs[1]->unit == UNIT_TR
2037 	  || regs[1]->unit == UNIT_TT)
2038 	{
2039 	  as_bad (_("PC, CT, TR and TT are treated as if they are a single unit but operands must be in different units"));
2040 	  return NULL;
2041 	}
2042       break;
2043 
2044     default:
2045       /* Registers must be in different units.  */
2046       if (regs[0]->unit == regs[1]->unit)
2047 	{
2048 	  as_bad (_("source and destination register must be in different units"));
2049 	  return NULL;
2050 	}
2051       break;
2052     }
2053 
2054   insn->bits = (template->meta_opcode
2055 		| (regs[1]->no << 19)
2056 		| (regs[0]->no << 14)
2057 		| (regs[1]->unit << 10)
2058 		| (regs[0]->unit << 5));
2059 
2060   insn->len = 4;
2061   return l;
2062 }
2063 
2064 /* Parse a JUMP instruction.  */
2065 static const char *
parse_jump(const char * line,metag_insn * insn,const insn_template * template)2066 parse_jump (const char *line, metag_insn *insn,
2067 	    const insn_template *template)
2068 {
2069   const char *l = line;
2070   const metag_reg *regs[1];
2071   int value = 0;
2072 
2073   l = parse_gp_regs (l, regs, 1);
2074 
2075   if (l == NULL)
2076     return NULL;
2077 
2078   if (!is_short_unit (regs[0]->unit))
2079     {
2080       as_bad (_("register unit must be one of %s"), SHORT_UNITS);
2081       return false;
2082     }
2083 
2084   l = skip_comma (l);
2085 
2086   if (l == NULL ||
2087       *l == END_OF_INSN)
2088     return NULL;
2089 
2090   l = parse_imm16 (l, insn, &value);
2091 
2092   if (l == NULL)
2093     return NULL;
2094 
2095   insn->bits = (template->meta_opcode |
2096 		(regs[0]->no << 19) |
2097 		(regs[0]->unit & SHORT_UNIT_MASK) |
2098 		((value & IMM16_MASK) << 3));
2099 
2100   insn->len = 4;
2101   return l;
2102 }
2103 
2104 /* Parse a 19bit immediate value.  */
2105 static const char *
parse_imm19(const char * line,metag_insn * insn,int * value)2106 parse_imm19 (const char *line, metag_insn *insn, int *value)
2107 {
2108   const char *l = line;
2109   char *save_input_line_pointer;
2110   expressionS *exp = &insn->reloc_exp;
2111 
2112   /* Skip #.  */
2113   if (*l == '#')
2114     l++;
2115 
2116   save_input_line_pointer = input_line_pointer;
2117   input_line_pointer = (char *) l;
2118 
2119   expression (exp);
2120 
2121   l = input_line_pointer;
2122   input_line_pointer = save_input_line_pointer;
2123 
2124   if (exp->X_op == O_absent || exp->X_op == O_big)
2125     {
2126       return NULL;
2127     }
2128   else if (exp->X_op == O_constant)
2129     {
2130       *value = exp->X_add_number;
2131     }
2132   else
2133     {
2134       if (exp->X_op == O_PIC_reloc)
2135 	{
2136 	  exp->X_op = O_symbol;
2137 
2138 	  if (exp->X_md == BFD_RELOC_METAG_PLT)
2139 	    insn->reloc_type = BFD_RELOC_METAG_RELBRANCH_PLT;
2140 	  else
2141 	    return NULL;
2142 	}
2143       else
2144 	insn->reloc_type = BFD_RELOC_METAG_RELBRANCH;
2145       insn->reloc_pcrel = 1;
2146     }
2147 
2148   return l;
2149 }
2150 
2151 /* Parse a CALLR instruction.  */
2152 static const char *
parse_callr(const char * line,metag_insn * insn,const insn_template * template)2153 parse_callr (const char *line, metag_insn *insn,
2154 	     const insn_template *template)
2155 {
2156   const char *l = line;
2157   const metag_reg *regs[1];
2158   int value = 0;
2159 
2160   l = parse_gp_regs (l, regs, 1);
2161 
2162   if (l == NULL)
2163     return NULL;
2164 
2165   if (!is_short_unit (regs[0]->unit))
2166     {
2167       as_bad (_("link register unit must be one of %s"), SHORT_UNITS);
2168       return NULL;
2169     }
2170 
2171   if (regs[0]->no & ~CALLR_REG_MASK)
2172     {
2173       as_bad (_("link register must be in a low numbered register"));
2174       return NULL;
2175     }
2176 
2177   l = skip_comma (l);
2178 
2179   if (l == NULL ||
2180       *l == END_OF_INSN)
2181     return NULL;
2182 
2183   l = parse_imm19 (l, insn, &value);
2184 
2185   if (l == NULL)
2186     return NULL;
2187 
2188   if (!within_signed_range (value / 4, IMM19_BITS))
2189     {
2190       as_bad (_("target out of range"));
2191       return NULL;
2192     }
2193 
2194   insn->bits = (template->meta_opcode |
2195 		(regs[0]->no & CALLR_REG_MASK) |
2196 		((regs[0]->unit & SHORT_UNIT_MASK) << 3) |
2197 		((value & IMM19_MASK) << 5));
2198 
2199   insn->len = 4;
2200   return l;
2201 }
2202 
2203 /* Return the value for the register field if we apply the O2R modifier
2204    to operand 2 REG, combined with UNIT_BIT derived from the destination
2205    register or source1. Uses address unit O2R if IS_ADDR is set.  */
2206 static int
lookup_o2r(unsigned int is_addr,unsigned int unit_bit,const metag_reg * reg)2207 lookup_o2r (unsigned int is_addr, unsigned int unit_bit, const metag_reg *reg)
2208 {
2209   if (reg->no & ~O2R_REG_MASK)
2210     return -1;
2211 
2212   if (is_addr)
2213     {
2214       if (unit_bit)
2215 	{
2216 	  switch (reg->unit)
2217 	    {
2218 	    case UNIT_D1:
2219 	      return reg->no;
2220 	    case UNIT_D0:
2221 	      return (1 << 3) | reg->no;
2222 	    case UNIT_RD:
2223 	      return (2 << 3) | reg->no;
2224 	    case UNIT_A0:
2225 	      return (3 << 3) | reg->no;
2226 	    default:
2227 	      return -1;
2228 	    }
2229 	}
2230       else
2231 	{
2232 	  switch (reg->unit)
2233 	    {
2234 	    case UNIT_A1:
2235 	      return reg->no;
2236 	    case UNIT_D0:
2237 	      return (1 << 3) | reg->no;
2238 	    case UNIT_RD:
2239 	      return (2 << 3) | reg->no;
2240 	    case UNIT_D1:
2241 	      return (3 << 3) | reg->no;
2242 	    default:
2243 	      return -1;
2244 	    }
2245 	}
2246     }
2247   else
2248     {
2249       if (unit_bit)
2250 	{
2251 	  switch (reg->unit)
2252 	    {
2253 	    case UNIT_A1:
2254 	      return reg->no;
2255 	    case UNIT_D0:
2256 	      return (1 << 3) | reg->no;
2257 	    case UNIT_RD:
2258 	      return (2 << 3) | reg->no;
2259 	    case UNIT_A0:
2260 	      return (3 << 3) | reg->no;
2261 	    default:
2262 	      return -1;
2263 	    }
2264 	}
2265       else
2266 	{
2267 	  switch (reg->unit)
2268 	    {
2269 	    case UNIT_A1:
2270 	      return reg->no;
2271 	    case UNIT_D1:
2272 	      return (1 << 3) | reg->no;
2273 	    case UNIT_RD:
2274 	      return (2 << 3) | reg->no;
2275 	    case UNIT_A0:
2276 	      return (3 << 3) | reg->no;
2277 	    default:
2278 	      return -1;
2279 	    }
2280 	}
2281     }
2282 }
2283 
2284 /* Parse GP ALU instruction.  */
2285 static const char *
parse_alu(const char * line,metag_insn * insn,const insn_template * template)2286 parse_alu (const char *line, metag_insn *insn,
2287 	   const insn_template *template)
2288 {
2289   const char *l = line;
2290   const metag_reg *dest_regs[1];
2291   const metag_reg *src_regs[2];
2292   int value = 0;
2293   bool o1z = 0;
2294   bool imm = ((template->meta_opcode >> 25) & 0x1) != 0;
2295   bool cond = ((template->meta_opcode >> 26) & 0x1) != 0;
2296   bool ca = ((template->meta_opcode >> 5) & 0x1) != 0;
2297   bool top = (template->meta_opcode & 0x1) != 0;
2298   bool sign_extend = 0;
2299   bool is_addr_op = MAJOR_OPCODE (template->meta_opcode) == OPC_ADDR;
2300   bool is_mul = MAJOR_OPCODE (template->meta_opcode) == OPC_MUL;
2301   unsigned int unit_bit = 0;
2302   bool is_quickrot = (template->arg_type & GP_ARGS_QR) != 0;
2303 
2304   l = parse_gp_regs (l, dest_regs, 1);
2305 
2306   if (l == NULL)
2307     return NULL;
2308 
2309   l = skip_comma (l);
2310 
2311   if (l == NULL ||
2312       *l == END_OF_INSN)
2313     return NULL;
2314 
2315   if (is_addr_op)
2316     {
2317       if (dest_regs[0]->unit == UNIT_A0)
2318 	unit_bit = 0;
2319       else if (dest_regs[0]->unit == UNIT_A1)
2320 	unit_bit = 1;
2321     }
2322   else
2323     {
2324       if (dest_regs[0]->unit == UNIT_D0)
2325 	unit_bit = 0;
2326       else if (dest_regs[0]->unit == UNIT_D1)
2327 	unit_bit = 1;
2328     }
2329 
2330   if ((MAJOR_OPCODE (template->meta_opcode) == OPC_ADDR ||
2331       MAJOR_OPCODE (template->meta_opcode) == OPC_ADD ||
2332        MAJOR_OPCODE (template->meta_opcode) == OPC_SUB) &&
2333       ((template->meta_opcode >> 2) & 0x1))
2334     o1z = 1;
2335 
2336   if (imm)
2337     {
2338       if (!cond)
2339 	{
2340 	  if (is_addr_op)
2341 	    {
2342 	      if (dest_regs[0]->unit == UNIT_A0)
2343 		unit_bit = 0;
2344 	      else if (dest_regs[0]->unit == UNIT_A1)
2345 		unit_bit = 1;
2346 	      else
2347 		return NULL;
2348 	    }
2349 	  else
2350 	    {
2351 	      if (dest_regs[0]->unit == UNIT_D0)
2352 		unit_bit = 0;
2353 	      else if (dest_regs[0]->unit == UNIT_D1)
2354 		unit_bit = 1;
2355 	      else
2356 		return NULL;
2357 	    }
2358 	}
2359 
2360       if (cond)
2361 	{
2362 	  l = parse_gp_regs (l, src_regs, 1);
2363 
2364 	  if (l == NULL)
2365 	    return NULL;
2366 
2367 	  l = skip_comma (l);
2368 
2369 	  if (l == NULL ||
2370 	      *l == END_OF_INSN)
2371 	    return NULL;
2372 
2373 	  if (is_addr_op)
2374 	    {
2375 	      if (src_regs[0]->unit == UNIT_A0)
2376 		unit_bit = 0;
2377 	      else if (src_regs[0]->unit == UNIT_A1)
2378 		unit_bit = 1;
2379 	      else
2380 		return NULL;
2381 	    }
2382 	  else
2383 	    {
2384 	      if (src_regs[0]->unit == UNIT_D0)
2385 		unit_bit = 0;
2386 	      else if (src_regs[0]->unit == UNIT_D1)
2387 		unit_bit = 1;
2388 	      else
2389 		return NULL;
2390 	    }
2391 
2392 	  if (src_regs[0]->unit != dest_regs[0]->unit && !ca)
2393 	    return NULL;
2394 
2395 	  l = parse_imm8 (l, insn, &value);
2396 
2397 	  if (l == NULL)
2398 	    return NULL;
2399 
2400 	  if (!within_unsigned_range (value, IMM8_BITS))
2401 	    return NULL;
2402 
2403 	  insn->bits = (template->meta_opcode |
2404 			(dest_regs[0]->no << 19) |
2405 			(src_regs[0]->no << 14) |
2406 			((value & IMM8_MASK) << 6));
2407 
2408 	  if (ca)
2409 	    {
2410 	      if (is_addr_op)
2411 		{
2412 		  if (src_regs[0]->unit == UNIT_A0)
2413 		    unit_bit = 0;
2414 		  else if (src_regs[0]->unit == UNIT_A1)
2415 		    unit_bit = 1;
2416 		  else
2417 		    return NULL;
2418 		}
2419 	      else
2420 		{
2421 		  if (src_regs[0]->unit == UNIT_D0)
2422 		    unit_bit = 0;
2423 		  else if (src_regs[0]->unit == UNIT_D1)
2424 		    unit_bit = 1;
2425 		  else
2426 		    return NULL;
2427 		}
2428 
2429 	      insn->bits |= dest_regs[0]->unit << 1;
2430 	    }
2431 	}
2432       else if (o1z)
2433 	{
2434 	  l = parse_imm16 (l, insn, &value);
2435 
2436 	  if (l == NULL)
2437 	    return NULL;
2438 
2439 	  if (value < 0)
2440 	    {
2441 	      if (!within_signed_range (value, IMM16_BITS))
2442 		{
2443 		  as_bad (_("immediate out of range"));
2444 		  return NULL;
2445 		}
2446 	      sign_extend = 1;
2447 	    }
2448 	  else
2449 	    {
2450 	      if (!within_unsigned_range (value, IMM16_BITS))
2451 		{
2452 		  as_bad (_("immediate out of range"));
2453 		  return NULL;
2454 		}
2455 	    }
2456 
2457 	  insn->bits = (template->meta_opcode |
2458 			(dest_regs[0]->no << 19) |
2459 			((value & IMM16_MASK) << 3));
2460 	}
2461       else
2462 	{
2463 	  l = parse_gp_regs (l, src_regs, 1);
2464 
2465 	  if (l == NULL)
2466 	    return NULL;
2467 
2468 	  if (!(src_regs[0]->unit == dest_regs[0]->unit))
2469 	    return NULL;
2470 
2471 	  /* CPC is valid for address ops. */
2472 	  if (src_regs[0]->no != dest_regs[0]->no &&
2473 	      !(is_addr_op && src_regs[0]->no == 0x10))
2474 	    return NULL;
2475 
2476 	  l = skip_comma (l);
2477 
2478 	  if (l == NULL ||
2479 	      *l == END_OF_INSN)
2480 	    return NULL;
2481 
2482 	  l = parse_imm16 (l, insn, &value);
2483 
2484 	  if (l == NULL)
2485 	    return NULL;
2486 
2487 	  if (value < 0)
2488 	    {
2489 	      if (!within_signed_range (value, IMM16_BITS))
2490 		{
2491 		  as_bad (_("immediate out of range"));
2492 		  return NULL;
2493 		}
2494 	      sign_extend = 1;
2495 	    }
2496 	  else
2497 	    {
2498 	      if (!within_unsigned_range (value, IMM16_BITS))
2499 		{
2500 		  as_bad (_("immediate out of range"));
2501 		  return NULL;
2502 		}
2503 	    }
2504 
2505 	  insn->bits = (template->meta_opcode |
2506 			(dest_regs[0]->no << 19) |
2507 			(src_regs[0]->no << 19) |
2508 			((value & IMM16_MASK) << 3));
2509 	}
2510     }
2511   else
2512     {
2513       bool o2r = 0;
2514       int rs2;
2515 
2516       if (cond || !o1z)
2517 	l = parse_gp_regs (l, src_regs, 2);
2518       else
2519 	l = parse_gp_regs (l, src_regs, 1);
2520 
2521       if (l == NULL)
2522 	return NULL;
2523 
2524       if (cond || !o1z)
2525 	{
2526 	  if (is_addr_op)
2527 	    {
2528 	      if (src_regs[0]->unit == UNIT_A0)
2529 		unit_bit = 0;
2530 	      else if (src_regs[0]->unit == UNIT_A1)
2531 		unit_bit = 1;
2532 	      else
2533 		return NULL;
2534 	    }
2535 	  else
2536 	    {
2537 	      if (src_regs[0]->unit == UNIT_D0)
2538 		unit_bit = 0;
2539 	      else if (src_regs[0]->unit == UNIT_D1)
2540 		unit_bit = 1;
2541 	      else
2542 		return NULL;
2543 	    }
2544 	}
2545       else
2546 	{
2547 	  if (is_addr_op)
2548 	    {
2549 	      if (dest_regs[0]->unit == UNIT_A0)
2550 		unit_bit = 0;
2551 	      else if (dest_regs[0]->unit == UNIT_A1)
2552 		unit_bit = 1;
2553 	      else
2554 		return NULL;
2555 	    }
2556 	  else
2557 	    {
2558 	      if (dest_regs[0]->unit == UNIT_D0)
2559 		unit_bit = 0;
2560 	      else if (dest_regs[0]->unit == UNIT_D1)
2561 		unit_bit = 1;
2562 	      else
2563 		return NULL;
2564 	    }
2565 	}
2566 
2567       if (cond)
2568 	{
2569 	  if (src_regs[0]->unit != src_regs[1]->unit)
2570 	    {
2571 	      rs2 = lookup_o2r (is_addr_op, unit_bit, src_regs[1]);
2572 
2573 	      if (rs2 < 0)
2574 		return NULL;
2575 
2576 	      o2r = 1;
2577 	    }
2578 	  else
2579 	    {
2580 	      rs2 = src_regs[1]->no;
2581 	    }
2582 
2583 	  insn->bits = (template->meta_opcode |
2584 			(dest_regs[0]->no << 19) |
2585 			(src_regs[0]->no << 14) |
2586 			(rs2 << 9));
2587 
2588 	  if (is_mul)
2589 	    {
2590 	      if (dest_regs[0]->unit != src_regs[0]->unit && is_mul)
2591 		{
2592 		  if (ca)
2593 		    {
2594 		      insn->bits |= dest_regs[0]->unit << 1;
2595 		    }
2596 		  else
2597 		    return NULL;
2598 		}
2599 	    }
2600 	  else
2601 	    insn->bits |= dest_regs[0]->unit << 5;
2602 	}
2603       else if (o1z)
2604 	{
2605 	  if (dest_regs[0]->unit != src_regs[0]->unit)
2606 	    {
2607 	      rs2 = lookup_o2r (is_addr_op, unit_bit, src_regs[0]);
2608 
2609 	      if (rs2 < 0)
2610 		return NULL;
2611 
2612 	      o2r = 1;
2613 	    }
2614 	  else
2615 	    {
2616 	      rs2 = src_regs[0]->no;
2617 	    }
2618 
2619 	  insn->bits = (template->meta_opcode |
2620 			(dest_regs[0]->no << 19) |
2621 			(rs2 << 9));
2622 	}
2623       else
2624 	{
2625 	  if (dest_regs[0]->unit != src_regs[0]->unit)
2626 	    return NULL;
2627 
2628 	  if (dest_regs[0]->unit != src_regs[1]->unit)
2629 	    {
2630 	      rs2 = lookup_o2r (is_addr_op, unit_bit, src_regs[1]);
2631 
2632 	      if (rs2 < 0)
2633 		return NULL;
2634 
2635 	      o2r = 1;
2636 	    }
2637 	  else
2638 	    {
2639 	      rs2 = src_regs[1]->no;
2640 	    }
2641 
2642 	  insn->bits = (template->meta_opcode |
2643 			(dest_regs[0]->no << 19) |
2644 			(src_regs[0]->no << 14) |
2645 			(rs2 << 9));
2646 	}
2647 
2648       if (o2r)
2649 	insn->bits |= 1;
2650     }
2651 
2652   if (is_quickrot)
2653     {
2654       const metag_reg *qr_regs[1];
2655       bool limit_regs = imm && cond;
2656 
2657       l = skip_comma (l);
2658 
2659       if (l == NULL ||
2660 	  *l == END_OF_INSN)
2661 	return NULL;
2662 
2663       l = parse_gp_regs (l, qr_regs, 1);
2664 
2665       if (l == NULL)
2666 	return NULL;
2667 
2668       if (!((unit_bit == 0 && qr_regs[0]->unit != UNIT_A0) ||
2669 	    !(unit_bit == 1 && qr_regs[0]->unit != UNIT_A1)))
2670 	{
2671 	  as_bad (_("invalid quickrot unit specified"));
2672 	  return NULL;
2673 	}
2674 
2675       switch (qr_regs[0]->no)
2676 	{
2677 	case 2:
2678 	  break;
2679 	case 3:
2680 	  if (!limit_regs)
2681 	    {
2682 	      insn->bits |= (1 << 7);
2683 	      break;
2684 	    }
2685 	  /* Fall through.  */
2686 	default:
2687 	  as_bad (_("invalid quickrot register specified"));
2688 	  return NULL;
2689 	}
2690     }
2691 
2692   if (sign_extend && !top)
2693     insn->bits |= (1 << 1);
2694 
2695   insn->bits |= unit_bit << 24;
2696   insn->len = 4;
2697   return l;
2698 }
2699 
2700 /* Parse a B instruction.  */
2701 static const char *
parse_branch(const char * line,metag_insn * insn,const insn_template * template)2702 parse_branch (const char *line, metag_insn *insn,
2703 	      const insn_template *template)
2704 {
2705   const char *l = line;
2706   int value = 0;
2707 
2708   l = parse_imm19 (l, insn, &value);
2709 
2710   if (l == NULL)
2711     return NULL;
2712 
2713   if (!within_signed_range (value / 4, IMM19_BITS))
2714     {
2715       as_bad (_("target out of range"));
2716       return NULL;
2717     }
2718 
2719   insn->bits = (template->meta_opcode |
2720 		((value & IMM19_MASK) << 5));
2721 
2722   insn->len = 4;
2723   return l;
2724 }
2725 
2726 /* Parse a KICK instruction.  */
2727 static const char *
parse_kick(const char * line,metag_insn * insn,const insn_template * template)2728 parse_kick (const char *line, metag_insn *insn,
2729 	    const insn_template *template)
2730 {
2731   const char *l = line;
2732   const metag_reg *regs[2];
2733 
2734   l = parse_gp_regs (l, regs, 2);
2735 
2736   if (l == NULL)
2737     return NULL;
2738 
2739   if (regs[1]->unit != UNIT_TR)
2740     {
2741       as_bad (_("source register must be in the trigger unit"));
2742       return NULL;
2743     }
2744 
2745   insn->bits = (template->meta_opcode |
2746 		(regs[1]->no << 19) |
2747 		(regs[0]->no << 14) |
2748 		(regs[0]->unit << 5));
2749 
2750   insn->len = 4;
2751   return l;
2752 }
2753 
2754 /* Parse a SWITCH instruction.  */
2755 static const char *
parse_switch(const char * line,metag_insn * insn,const insn_template * template)2756 parse_switch (const char *line, metag_insn *insn,
2757 	      const insn_template *template)
2758 {
2759   const char *l = line;
2760   int value = 0;
2761 
2762   l = parse_imm_constant (l, insn, &value);
2763 
2764   if (l == NULL)
2765     return NULL;
2766 
2767   if (!within_unsigned_range (value, IMM24_BITS))
2768     {
2769       as_bad (_("target out of range"));
2770       return NULL;
2771     }
2772 
2773   insn->bits = (template->meta_opcode |
2774 		(value & IMM24_MASK));
2775 
2776   insn->len = 4;
2777   return l;
2778 }
2779 
2780 /* Parse a shift instruction.  */
2781 static const char *
parse_shift(const char * line,metag_insn * insn,const insn_template * template)2782 parse_shift (const char *line, metag_insn *insn,
2783 	     const insn_template *template)
2784 {
2785   const char *l = line;
2786   const metag_reg *regs[2];
2787   const metag_reg *src2_regs[1];
2788   int value = 0;
2789   bool cond = ((template->meta_opcode >> 26) & 0x1) != 0;
2790   bool ca = ((template->meta_opcode >> 5) & 0x1) != 0;
2791   unsigned int unit_bit = 0;
2792 
2793   l = parse_gp_regs (l, regs, 2);
2794 
2795   if (l == NULL)
2796     return NULL;
2797 
2798   l = skip_comma (l);
2799 
2800   if (l == NULL ||
2801       *l == END_OF_INSN)
2802     return NULL;
2803 
2804   if (regs[1]->unit == UNIT_D0)
2805     unit_bit = 0;
2806   else if (regs[1]->unit == UNIT_D1)
2807     unit_bit = 1;
2808   else
2809     return NULL;
2810 
2811   if (regs[0]->unit != regs[1]->unit && !(cond && ca))
2812     return NULL;
2813 
2814   if (*l == '#')
2815     {
2816       l = parse_imm_constant (l, insn, &value);
2817 
2818       if (l == NULL)
2819 	return NULL;
2820 
2821       if (!within_unsigned_range (value, IMM5_BITS))
2822 	return NULL;
2823 
2824       insn->bits = (template->meta_opcode |
2825 		    (1 << 25) |
2826 		    (regs[0]->no << 19) |
2827 		    (regs[1]->no << 14) |
2828 		    ((value & IMM5_MASK) << 9));
2829     }
2830   else
2831     {
2832       l = parse_gp_regs (l, src2_regs, 1);
2833 
2834       if (l == NULL)
2835 	return NULL;
2836 
2837       insn->bits = (template->meta_opcode |
2838 		    (regs[0]->no << 19) |
2839 		    (regs[1]->no << 14) |
2840 		    (src2_regs[0]->no << 9));
2841 
2842       if (src2_regs[0]->unit != regs[1]->unit)
2843 	{
2844 	  as_bad(_("Source registers must be in the same unit"));
2845 	  return NULL;
2846 	}
2847     }
2848 
2849   if (regs[0]->unit != regs[1]->unit)
2850     {
2851       if (cond && ca)
2852 	{
2853 	  if (regs[1]->unit == UNIT_D0)
2854 	    unit_bit = 0;
2855 	  else if (regs[1]->unit == UNIT_D1)
2856 	    unit_bit = 1;
2857 	  else
2858 	    return NULL;
2859 
2860 	  insn->bits |= ((1 << 5) |
2861 			 (regs[0]->unit << 1));
2862 	}
2863       else
2864 	return NULL;
2865     }
2866 
2867   insn->bits |= unit_bit << 24;
2868   insn->len = 4;
2869   return l;
2870 }
2871 
2872 /* Parse a MIN or MAX instruction.  */
2873 static const char *
parse_min_max(const char * line,metag_insn * insn,const insn_template * template)2874 parse_min_max (const char *line, metag_insn *insn,
2875 	       const insn_template *template)
2876 {
2877   const char *l = line;
2878   const metag_reg *regs[3];
2879 
2880   l = parse_gp_regs (l, regs, 3);
2881 
2882   if (l == NULL)
2883     return NULL;
2884 
2885   if (!(regs[0]->unit == UNIT_D0 ||
2886 	regs[0]->unit == UNIT_D1))
2887       return NULL;
2888 
2889   if (!(regs[0]->unit == regs[1]->unit &&
2890 	regs[1]->unit == regs[2]->unit))
2891       return NULL;
2892 
2893   insn->bits = (template->meta_opcode |
2894 		(regs[0]->no << 19) |
2895 		(regs[1]->no << 14) |
2896 		(regs[2]->no << 9));
2897 
2898   if (regs[0]->unit == UNIT_D1)
2899     insn->bits |= (1 << 24);
2900 
2901   insn->len = 4;
2902   return l;
2903 }
2904 
2905 /* Parse a bit operation instruction.  */
2906 static const char *
parse_bitop(const char * line,metag_insn * insn,const insn_template * template)2907 parse_bitop (const char *line, metag_insn *insn,
2908 	     const insn_template *template)
2909 {
2910   const char *l = line;
2911   const metag_reg *regs[2];
2912   bool swap_inst = MAJOR_OPCODE (template->meta_opcode) == OPC_MISC;
2913   bool is_bexl = 0;
2914 
2915   if (swap_inst && ((template->meta_opcode >> 1) & 0xb) == 0xa)
2916     is_bexl = 1;
2917 
2918   l = parse_gp_regs (l, regs, 2);
2919 
2920   if (l == NULL)
2921     return NULL;
2922 
2923   if (!(regs[0]->unit == UNIT_D0 ||
2924 	regs[0]->unit == UNIT_D1))
2925       return NULL;
2926 
2927   if (is_bexl)
2928     {
2929       if (regs[0]->unit == UNIT_D0 &&
2930 	  regs[1]->unit != UNIT_D1)
2931 	return NULL;
2932       else if (regs[0]->unit == UNIT_D1 &&
2933 	       regs[1]->unit != UNIT_D0)
2934 	return NULL;
2935     }
2936   else if (!(regs[0]->unit == regs[1]->unit))
2937       return NULL;
2938 
2939   insn->bits = (template->meta_opcode |
2940 		(regs[0]->no << 19) |
2941 		(regs[1]->no << 14));
2942 
2943   if (swap_inst)
2944     {
2945       if (regs[1]->unit == UNIT_D1)
2946 	insn->bits |= 1;
2947     }
2948   else
2949     {
2950       if (regs[1]->unit == UNIT_D1)
2951 	insn->bits |= (1 << 24);
2952     }
2953 
2954   insn->len = 4;
2955   return l;
2956 }
2957 
2958 /* Parse a CMP or TST instruction.  */
2959 static const char *
parse_cmp(const char * line,metag_insn * insn,const insn_template * template)2960 parse_cmp (const char *line, metag_insn *insn,
2961 	   const insn_template *template)
2962 {
2963   const char *l = line;
2964   const metag_reg *dest_regs[1];
2965   const metag_reg *src_regs[1];
2966   int value = 0;
2967   bool imm = ((template->meta_opcode >> 25) & 0x1) != 0;
2968   bool cond = ((template->meta_opcode >> 26) & 0x1) != 0;
2969   bool top = (template->meta_opcode & 0x1) != 0;
2970   bool sign_extend = 0;
2971   unsigned int unit_bit = 0;
2972 
2973   l = parse_gp_regs (l, dest_regs, 1);
2974 
2975   if (l == NULL)
2976     return NULL;
2977 
2978   l = skip_comma (l);
2979 
2980   if (l == NULL ||
2981       *l == END_OF_INSN)
2982     return NULL;
2983 
2984   if (dest_regs[0]->unit == UNIT_D0)
2985     unit_bit = 0;
2986   else if (dest_regs[0]->unit == UNIT_D1)
2987     unit_bit = 1;
2988   else
2989     return NULL;
2990 
2991   if (imm)
2992     {
2993       if (cond)
2994 	{
2995 	  l = parse_imm_constant (l, insn, &value);
2996 
2997 	  if (l == NULL)
2998 	    return NULL;
2999 
3000 	  if (!within_unsigned_range (value, IMM8_BITS))
3001 	    return NULL;
3002 
3003 	  insn->bits = (template->meta_opcode |
3004 			(dest_regs[0]->no << 14) |
3005 			((value & IMM8_MASK) << 6));
3006 
3007 	}
3008       else
3009 	{
3010 	  l = parse_imm16 (l, insn, &value);
3011 
3012 	  if (l == NULL)
3013 	    return NULL;
3014 
3015 	  if (value < 0)
3016 	    {
3017 	      if (!within_signed_range (value, IMM16_BITS))
3018 		{
3019 		  as_bad (_("immediate out of range"));
3020 		  return NULL;
3021 		}
3022 	      sign_extend = 1;
3023 	    }
3024 	  else
3025 	    {
3026 	      if (!within_unsigned_range (value, IMM16_BITS))
3027 		{
3028 		  as_bad (_("immediate out of range"));
3029 		  return NULL;
3030 		}
3031 	    }
3032 
3033 	  insn->bits = (template->meta_opcode |
3034 			(dest_regs[0]->no << 19) |
3035 			((value & IMM16_MASK) << 3));
3036 	}
3037     }
3038   else
3039     {
3040       bool o2r = 0;
3041       int rs2;
3042 
3043       l = parse_gp_regs (l, src_regs, 1);
3044 
3045       if (l == NULL)
3046 	return NULL;
3047 
3048       if (dest_regs[0]->unit != src_regs[0]->unit)
3049 	{
3050 	  rs2 = lookup_o2r (0, unit_bit, src_regs[0]);
3051 
3052 	  if (rs2 < 0)
3053 	    return NULL;
3054 
3055 	  o2r = 1;
3056 	}
3057       else
3058 	{
3059 	  rs2 = src_regs[0]->no;
3060 	}
3061 
3062       insn->bits = (template->meta_opcode |
3063 		    (dest_regs[0]->no << 14) |
3064 		    (rs2 << 9));
3065 
3066       if (o2r)
3067 	insn->bits |= 1;
3068     }
3069 
3070   if (sign_extend && !top)
3071     insn->bits |= (1 << 1);
3072 
3073   insn->bits |= unit_bit << 24;
3074   insn->len = 4;
3075   return l;
3076 }
3077 
3078 /* Parse a CACHEW instruction.  */
3079 static const char *
parse_cachew(const char * line,metag_insn * insn,const insn_template * template)3080 parse_cachew (const char *line, metag_insn *insn,
3081 	      const insn_template *template)
3082 {
3083   const char *l = line;
3084   const metag_reg *src_regs[2];
3085   unsigned int size = ((template->meta_opcode >> 1) & 0x1) ? 8 : 4;
3086   metag_addr addr;
3087   int offset;
3088 
3089   memset(&addr, 0, sizeof(addr));
3090   addr.reloc_type = BFD_RELOC_UNUSED;
3091 
3092   l = parse_addr (l, &addr, size);
3093 
3094   if (l == NULL ||
3095       !is_short_unit (addr.base_reg->unit) ||
3096       addr.update ||
3097       !addr.immediate)
3098     {
3099 	  as_bad (_("invalid memory operand"));
3100 	  return NULL;
3101     }
3102 
3103   l = skip_comma (l);
3104 
3105   if (l == NULL ||
3106       *l == END_OF_INSN)
3107     return NULL;
3108 
3109   if (size == 4)
3110     l = parse_gp_regs (l, src_regs, 1);
3111   else
3112     l = parse_pair_gp_regs (l, src_regs);
3113 
3114   if (l == NULL ||
3115       !is_short_unit (src_regs[0]->unit))
3116     {
3117       as_bad (_("invalid source register"));
3118       return NULL;
3119     }
3120 
3121   offset = addr.exp.X_add_number;
3122 
3123   if (addr.negate)
3124     offset = -offset;
3125 
3126   offset = offset / 64;
3127 
3128   if (!within_signed_range (offset, GET_SET_IMM_BITS))
3129     {
3130       as_bad (_("offset value out of range"));
3131       return NULL;
3132     }
3133 
3134   insn->bits = (template->meta_opcode |
3135 		(src_regs[0]->no << 19) |
3136 		(addr.base_reg->no << 14) |
3137 		((offset & GET_SET_IMM_MASK) << 8) |
3138 		((addr.base_reg->unit & SHORT_UNIT_MASK) << 5) |
3139 		((src_regs[0]->unit & SHORT_UNIT_MASK) << 3));
3140 
3141   insn->len = 4;
3142   return l;
3143 }
3144 
3145 /* Parse a CACHEW instruction.  */
3146 static const char *
parse_cacher(const char * line,metag_insn * insn,const insn_template * template)3147 parse_cacher (const char *line, metag_insn *insn,
3148 	      const insn_template *template)
3149 {
3150   const char *l = line;
3151   const metag_reg *dest_regs[2];
3152   unsigned int size = ((template->meta_opcode >> 1) & 0x1) ? 8 : 4;
3153   metag_addr addr;
3154   int offset;
3155 
3156   memset(&addr, 0, sizeof(addr));
3157   addr.reloc_type = BFD_RELOC_UNUSED;
3158 
3159   if (size == 4)
3160     l = parse_gp_regs (l, dest_regs, 1);
3161   else
3162     l = parse_pair_gp_regs (l, dest_regs);
3163 
3164   if (l == NULL ||
3165       !is_short_unit (dest_regs[0]->unit))
3166     {
3167       as_bad (_("invalid destination register"));
3168       return NULL;
3169     }
3170 
3171   l = skip_comma (l);
3172 
3173   if (l == NULL ||
3174       *l == END_OF_INSN)
3175     return NULL;
3176 
3177   l = parse_addr (l, &addr, size);
3178 
3179   if (l == NULL ||
3180       !is_short_unit (addr.base_reg->unit) ||
3181       addr.update ||
3182       !addr.immediate)
3183     {
3184 	  as_bad (_("invalid memory operand"));
3185 	  return NULL;
3186     }
3187 
3188   offset = addr.exp.X_add_number;
3189 
3190   if (addr.negate)
3191     offset = -offset;
3192 
3193   offset = offset / (int)size;
3194 
3195   if (!within_signed_range (offset, GET_SET_IMM_BITS))
3196     {
3197       as_bad (_("offset value out of range"));
3198       return NULL;
3199     }
3200 
3201   insn->bits = (template->meta_opcode |
3202 		(dest_regs[0]->no << 19) |
3203 		(addr.base_reg->no << 14) |
3204 		((offset & GET_SET_IMM_MASK) << 8) |
3205 		((addr.base_reg->unit & SHORT_UNIT_MASK) << 5) |
3206 		((dest_regs[0]->unit & SHORT_UNIT_MASK) << 3));
3207 
3208   insn->len = 4;
3209   return l;
3210 }
3211 
3212 /* Parse an ICACHE instruction.  */
3213 static const char *
parse_icache(const char * line,metag_insn * insn,const insn_template * template)3214 parse_icache (const char *line, metag_insn *insn,
3215 	      const insn_template *template)
3216 {
3217   const char *l = line;
3218   int offset;
3219   int pfcount;
3220 
3221   l = parse_imm_constant (l, insn, &offset);
3222 
3223   if (l == NULL)
3224     return NULL;
3225 
3226   if (!within_signed_range (offset, IMM15_BITS))
3227     return NULL;
3228 
3229   l = skip_comma (l);
3230 
3231   l = parse_imm_constant (l, insn, &pfcount);
3232 
3233   if (l == NULL)
3234     return NULL;
3235 
3236   if (!within_unsigned_range (pfcount, IMM4_BITS))
3237     return NULL;
3238 
3239   insn->bits = (template->meta_opcode |
3240 		((offset & IMM15_MASK) << 9) |
3241 		((pfcount & IMM4_MASK) << 1));
3242 
3243   insn->len = 4;
3244   return l;
3245 }
3246 
3247 /* Parse a LNKGET instruction.  */
3248 static const char *
parse_lnkget(const char * line,metag_insn * insn,const insn_template * template)3249 parse_lnkget (const char *line, metag_insn *insn,
3250 	      const insn_template *template)
3251 {
3252   const char *l = line;
3253   const metag_reg *dest_regs[2];
3254   unsigned int size = metag_get_set_ext_size_bytes (template->meta_opcode);
3255   metag_addr addr;
3256   int offset;
3257 
3258   memset(&addr, 0, sizeof(addr));
3259   addr.reloc_type = BFD_RELOC_UNUSED;
3260 
3261   if (size == 8)
3262     l = parse_pair_gp_regs (l, dest_regs);
3263   else
3264     l = parse_gp_regs (l, dest_regs, 1);
3265 
3266   if (l == NULL ||
3267       !is_short_unit (dest_regs[0]->unit))
3268     {
3269       as_bad (_("invalid destination register"));
3270       return NULL;
3271     }
3272 
3273   l = skip_comma (l);
3274 
3275   if (l == NULL ||
3276       *l == END_OF_INSN)
3277     return NULL;
3278 
3279   l = parse_addr (l, &addr, size);
3280 
3281   if (l == NULL ||
3282       !is_short_unit (addr.base_reg->unit) ||
3283       addr.update ||
3284       !addr.immediate)
3285     {
3286 	  as_bad (_("invalid memory operand"));
3287 	  return NULL;
3288     }
3289 
3290   offset = addr.exp.X_add_number;
3291 
3292   if (addr.negate)
3293     offset = -offset;
3294 
3295   offset = offset / size;
3296 
3297   if (!within_signed_range (offset, GET_SET_IMM_BITS))
3298     {
3299       as_bad (_("offset value out of range"));
3300       return NULL;
3301     }
3302 
3303   insn->bits = (template->meta_opcode |
3304 		(dest_regs[0]->no << 19) |
3305 		(addr.base_reg->no << 14) |
3306 		((offset & GET_SET_IMM_MASK) << 8) |
3307 		((addr.base_reg->unit & SHORT_UNIT_MASK) << 5) |
3308 		((dest_regs[0]->unit & SHORT_UNIT_MASK) << 3));
3309 
3310   insn->len = 4;
3311   return l;
3312 }
3313 
3314 /* Parse an FPU MOV instruction.  */
3315 static const char *
parse_fmov(const char * line,metag_insn * insn,const insn_template * template)3316 parse_fmov (const char *line, metag_insn *insn,
3317 	    const insn_template *template)
3318 {
3319   const char *l = line;
3320   const metag_reg *regs[2];
3321 
3322   l = parse_fpu_regs (l, regs, 2);
3323 
3324   if (l == NULL)
3325     return NULL;
3326 
3327   insn->bits = (template->meta_opcode |
3328 		(regs[0]->no << 19) |
3329 		(regs[1]->no << 14));
3330 
3331   if (insn->fpu_width == FPU_WIDTH_DOUBLE)
3332     insn->bits |= (1 << 5);
3333   else if (insn->fpu_width == FPU_WIDTH_PAIR)
3334     insn->bits |= (1 << 6);
3335 
3336   insn->len = 4;
3337   return l;
3338 }
3339 
3340 /* Parse an FPU MMOV instruction.  */
3341 static const char *
parse_fmmov(const char * line,metag_insn * insn,const insn_template * template)3342 parse_fmmov (const char *line, metag_insn *insn,
3343 	     const insn_template *template)
3344 {
3345   const char *l = line;
3346   bool to_fpu = MAJOR_OPCODE (template->meta_opcode) == OPC_GET;
3347   bool is_mmovl = (MINOR_OPCODE (template->meta_opcode) & 0x1) != 0;
3348   size_t regs_read = 0;
3349   const metag_reg *regs[16];
3350   unsigned int lowest_data_reg = 0xffffffff;
3351   unsigned int lowest_fpu_reg = 0xffffffff;
3352   unsigned int rmask = 0, data_unit;
3353   size_t i;
3354   int last_reg = -1;
3355 
3356   if (insn->fpu_width != FPU_WIDTH_SINGLE)
3357     return NULL;
3358 
3359   l = parse_gp_regs_list (l, regs, 16, &regs_read);
3360 
3361   if (l == NULL)
3362     return NULL;
3363 
3364   if (regs_read % 2)
3365     return NULL;
3366 
3367   if (to_fpu)
3368     {
3369       for (i = 0; i < regs_read / 2; i++)
3370 	{
3371 	  if (regs[i]->unit != UNIT_FX)
3372 	    return NULL;
3373 
3374 	  if (last_reg == -1)
3375 	    {
3376 	      last_reg = regs[i]->no;
3377 	      lowest_fpu_reg = last_reg;
3378 	    }
3379 	  else
3380 	    {
3381 	      if (is_mmovl)
3382 		{
3383 		  if (regs[i]->no != (unsigned int)(last_reg + 2))
3384 		    return NULL;
3385 		}
3386 	      else if (regs[i]->no != (unsigned int)(last_reg + 1))
3387 		return NULL;
3388 
3389 	      last_reg = regs[i]->no;
3390 	    }
3391 	}
3392 
3393       if (regs[i]->unit == UNIT_D0)
3394 	data_unit = 0;
3395       else if (regs[i]->unit == UNIT_D1)
3396 	data_unit = 1;
3397       else
3398 	return NULL;
3399 
3400       if (!check_rmask (&regs[i], regs_read / 2, true, false, &lowest_data_reg,
3401 			&rmask))
3402 	return NULL;
3403     }
3404   else
3405     {
3406       if (regs[0]->unit == UNIT_D0)
3407 	data_unit = 0;
3408       else if (regs[0]->unit == UNIT_D1)
3409 	data_unit = 1;
3410       else
3411 	return NULL;
3412 
3413       if (!check_rmask (regs, regs_read / 2, true, false, &lowest_data_reg,
3414 			&rmask))
3415 	return NULL;
3416 
3417       for (i = regs_read / 2; i < regs_read; i++)
3418 	{
3419 	  if (regs[i]->unit != UNIT_FX)
3420 	    return NULL;
3421 
3422 	  if (last_reg == -1)
3423 	    {
3424 	      last_reg = regs[i]->no;
3425 	      lowest_fpu_reg = last_reg;
3426 	    }
3427 	  else
3428 	    {
3429 	      if (is_mmovl)
3430 		{
3431 		  if (regs[i]->no != (unsigned int)(last_reg + 2))
3432 		    return NULL;
3433 		}
3434 	      else if (regs[i]->no != (unsigned int)(last_reg + 1))
3435 		return NULL;
3436 
3437 	      last_reg = regs[i]->no;
3438 	    }
3439 	}
3440     }
3441 
3442   insn->bits = (template->meta_opcode |
3443 		((lowest_data_reg & REG_MASK) << 19) |
3444 		((lowest_fpu_reg & REG_MASK) << 14) |
3445 		((rmask & RMASK_MASK) << 7) |
3446 		data_unit);
3447 
3448   insn->len = 4;
3449   return l;
3450 }
3451 
3452 /* Parse an FPU data unit MOV instruction.  */
3453 static const char *
parse_fmov_data(const char * line,metag_insn * insn,const insn_template * template)3454 parse_fmov_data (const char *line, metag_insn *insn,
3455 	    const insn_template *template)
3456 {
3457   const char *l = line;
3458   bool to_fpu = ((template->meta_opcode >> 7) & 0x1) != 0;
3459   const metag_reg *regs[2];
3460   unsigned int base_unit;
3461 
3462   if (insn->fpu_width == FPU_WIDTH_PAIR)
3463     return NULL;
3464 
3465   l = parse_gp_regs (l, regs, 2);
3466 
3467   if (l == NULL)
3468     return NULL;
3469 
3470   if (to_fpu)
3471     {
3472       if (regs[0]->unit != UNIT_FX)
3473 	return NULL;
3474 
3475       if (regs[1]->unit == UNIT_D0)
3476 	base_unit = 0;
3477       else if (regs[1]->unit == UNIT_D1)
3478 	base_unit = 1;
3479       else
3480 	return NULL;
3481     }
3482   else
3483     {
3484       if (regs[0]->unit == UNIT_D0)
3485 	base_unit = 0;
3486       else if (regs[0]->unit == UNIT_D1)
3487 	base_unit = 1;
3488       else
3489 	return NULL;
3490 
3491       if (regs[1]->unit != UNIT_FX)
3492 	return NULL;
3493     }
3494 
3495   insn->bits = (template->meta_opcode |
3496 		(base_unit << 24) |
3497 		(regs[0]->no << 19) |
3498 		(regs[1]->no << 9));
3499 
3500   insn->len = 4;
3501   return l;
3502 }
3503 
3504 /* Parse an FPU immediate MOV instruction.  */
3505 static const char *
parse_fmov_i(const char * line,metag_insn * insn,const insn_template * template)3506 parse_fmov_i (const char *line, metag_insn *insn,
3507 	      const insn_template *template)
3508 {
3509   const char *l = line;
3510   const metag_reg *regs[1];
3511   int value = 0;
3512 
3513   l = parse_fpu_regs (l, regs, 1);
3514 
3515   l = skip_comma (l);
3516 
3517   if (l == NULL ||
3518       *l == END_OF_INSN)
3519     return NULL;
3520 
3521   l = parse_imm16 (l, insn, &value);
3522 
3523   if (l == NULL)
3524     return NULL;
3525 
3526   insn->bits = (template->meta_opcode |
3527 		(regs[0]->no << 19) |
3528 		((value & IMM16_MASK) << 3));
3529 
3530   if (insn->fpu_width == FPU_WIDTH_DOUBLE)
3531     insn->bits |= (1 << 1);
3532   else if (insn->fpu_width == FPU_WIDTH_PAIR)
3533     insn->bits |= (1 << 2);
3534 
3535   insn->len = 4;
3536   return l;
3537 }
3538 
3539 /* Parse an FPU PACK instruction.  */
3540 static const char *
parse_fpack(const char * line,metag_insn * insn,const insn_template * template)3541 parse_fpack (const char *line, metag_insn *insn,
3542 	     const insn_template *template)
3543 {
3544   const char *l = line;
3545   const metag_reg *regs[3];
3546 
3547   l = parse_fpu_regs (l, regs, 3);
3548 
3549   if (l == NULL)
3550     return NULL;
3551 
3552   if (regs[0]->no % 2)
3553     {
3554       as_bad (_("destination register should be even numbered"));
3555       return NULL;
3556     }
3557 
3558   insn->bits = (template->meta_opcode |
3559 		(regs[0]->no << 19) |
3560 		(regs[1]->no << 14) |
3561 		(regs[2]->no << 9));
3562 
3563   insn->len = 4;
3564   return l;
3565 }
3566 
3567 /* Parse an FPU SWAP instruction.  */
3568 static const char *
parse_fswap(const char * line,metag_insn * insn,const insn_template * template)3569 parse_fswap (const char *line, metag_insn *insn,
3570 	     const insn_template *template)
3571 {
3572   const char *l = line;
3573   const metag_reg *regs[2];
3574 
3575   if (insn->fpu_width != FPU_WIDTH_PAIR)
3576     return NULL;
3577 
3578   l = parse_fpu_regs (l, regs, 2);
3579 
3580   if (l == NULL)
3581     return NULL;
3582 
3583   if (regs[0]->no % 2)
3584     return NULL;
3585 
3586   if (regs[1]->no % 2)
3587     return NULL;
3588 
3589   insn->bits = (template->meta_opcode |
3590 		(regs[0]->no << 19) |
3591 		(regs[1]->no << 14));
3592 
3593   insn->len = 4;
3594   return l;
3595 }
3596 
3597 /* Parse an FPU CMP instruction.  */
3598 static const char *
parse_fcmp(const char * line,metag_insn * insn,const insn_template * template)3599 parse_fcmp (const char *line, metag_insn *insn,
3600 	    const insn_template *template)
3601 {
3602   const char *l = line, *l2;
3603   const metag_reg *regs1[1];
3604   const metag_reg *regs2[1];
3605 
3606   l = parse_fpu_regs (l, regs1, 1);
3607 
3608   l = skip_comma (l);
3609 
3610   if (l == NULL ||
3611       *l == END_OF_INSN)
3612     return NULL;
3613 
3614   l2 = parse_fpu_regs (l, regs2, 1);
3615 
3616   if (l2 != NULL)
3617     {
3618       insn->bits = (regs2[0]->no << 9);
3619     }
3620   else
3621     {
3622       int constant = 0;
3623       l2 = parse_imm_constant (l, insn, &constant);
3624       if (!l2 || constant != 0)
3625 	{
3626 	  as_bad (_("comparison must be with register or #0"));
3627 	  return NULL;
3628 	}
3629       insn->bits = (1 << 8);
3630     }
3631 
3632   insn->bits |= (template->meta_opcode |
3633 		 (regs1[0]->no << 14));
3634 
3635   if (insn->fpu_action_flags & FPU_ACTION_ABS)
3636     insn->bits |= (1 << 19);
3637 
3638   if (insn->fpu_action_flags & FPU_ACTION_QUIET)
3639     insn->bits |= (1 << 7);
3640 
3641   if (insn->fpu_width == FPU_WIDTH_PAIR)
3642     insn->bits |= (1 << 6);
3643   else if (insn->fpu_width == FPU_WIDTH_DOUBLE)
3644     insn->bits |= (1 << 5);
3645 
3646   insn->len = 4;
3647   return l2;
3648 }
3649 
3650 /* Parse an FPU MIN or MAX instruction.  */
3651 static const char *
parse_fminmax(const char * line,metag_insn * insn,const insn_template * template)3652 parse_fminmax (const char *line, metag_insn *insn,
3653 	       const insn_template *template)
3654 {
3655   const char *l = line;
3656   const metag_reg *regs[3];
3657 
3658   l = parse_fpu_regs (l, regs, 3);
3659 
3660   if (l == NULL)
3661     return NULL;
3662 
3663   insn->bits = (template->meta_opcode |
3664 		(regs[0]->no << 19) |
3665 		(regs[1]->no << 14) |
3666 		(regs[2]->no << 9));
3667 
3668   if (insn->fpu_width == FPU_WIDTH_PAIR)
3669     insn->bits |= (1 << 6);
3670   else if (insn->fpu_width == FPU_WIDTH_DOUBLE)
3671     insn->bits |= (1 << 5);
3672 
3673   insn->len = 4;
3674   return l;
3675 }
3676 
3677 /* Parse an FPU data conversion instruction.  */
3678 static const char *
parse_fconv(const char * line,metag_insn * insn,const insn_template * template)3679 parse_fconv (const char *line, metag_insn *insn,
3680 	     const insn_template *template)
3681 {
3682   const char *l = line;
3683   const metag_reg *regs[2];
3684 
3685   if (insn->fpu_width == FPU_WIDTH_PAIR)
3686     {
3687       if (strncasecmp (template->name, "FTOH", 4) &&
3688 	  strncasecmp (template->name, "HTOF", 4) &&
3689 	  strncasecmp (template->name, "FTOI", 4) &&
3690 	  strncasecmp (template->name, "ITOF", 4))
3691 	{
3692 	  as_bad (_("instruction cannot operate on pair values"));
3693 	  return NULL;
3694 	}
3695     }
3696 
3697   if (insn->fpu_action_flags & FPU_ACTION_ZERO)
3698     {
3699       if (strncasecmp (template->name, "FTOI", 4) &&
3700 	  strncasecmp (template->name, "DTOI", 4) &&
3701 	  strncasecmp (template->name, "DTOL", 4))
3702 	{
3703 	  as_bad (_("zero flag is not valid for this instruction"));
3704 	  return NULL;
3705 	}
3706     }
3707 
3708   l = parse_fpu_regs (l, regs, 2);
3709 
3710   if (l == NULL)
3711     return NULL;
3712 
3713   if (!strncasecmp (template->name, "DTOL", 4) ||
3714       !strncasecmp (template->name, "LTOD", 4))
3715     {
3716       if (regs[0]->no % 2)
3717 	{
3718 	  as_bad (_("destination register should be even numbered"));
3719 	  return NULL;
3720 	}
3721 
3722       if (regs[1]->no % 2)
3723 	{
3724 	  as_bad (_("source register should be even numbered"));
3725 	  return NULL;
3726 	}
3727     }
3728 
3729   insn->bits = (template->meta_opcode |
3730 		(regs[0]->no << 19) |
3731 		(regs[1]->no << 14));
3732 
3733   if (insn->fpu_width == FPU_WIDTH_PAIR)
3734     insn->bits |= (1 << 6);
3735 
3736   if (insn->fpu_action_flags & FPU_ACTION_ZERO)
3737     insn->bits |= (1 << 12);
3738 
3739   insn->len = 4;
3740   return l;
3741 }
3742 
3743 /* Parse an FPU extended data conversion instruction.  */
3744 static const char *
parse_fconvx(const char * line,metag_insn * insn,const insn_template * template)3745 parse_fconvx (const char *line, metag_insn *insn,
3746 	      const insn_template *template)
3747 {
3748   const char *l = line;
3749   const metag_reg *regs[2];
3750   int fraction_bits = 0;
3751 
3752   if (insn->fpu_width == FPU_WIDTH_PAIR)
3753     {
3754       if (strncasecmp (template->name, "FTOX", 4) &&
3755 	  strncasecmp (template->name, "XTOF", 4))
3756 	{
3757 	  as_bad (_("instruction cannot operate on pair values"));
3758 	  return NULL;
3759 	}
3760     }
3761 
3762   l = parse_fpu_regs (l, regs, 2);
3763 
3764   l = skip_comma (l);
3765 
3766   if (l == NULL ||
3767       *l == END_OF_INSN)
3768     return NULL;
3769 
3770   l = parse_imm_constant (l, insn, &fraction_bits);
3771 
3772   if (l == NULL)
3773     return NULL;
3774 
3775   insn->bits = (template->meta_opcode |
3776 		(regs[0]->no << 19) |
3777 		(regs[1]->no << 14));
3778 
3779   if (strncasecmp (template->name, "DTOXL", 5) &&
3780       strncasecmp (template->name, "XLTOD", 5))
3781     {
3782       if (!within_unsigned_range (fraction_bits, IMM5_BITS))
3783 	{
3784 	  as_bad (_("fraction bits value out of range"));
3785 	  return NULL;
3786 	}
3787       insn->bits |= ((fraction_bits & IMM5_MASK) << 9);
3788     }
3789   else
3790     {
3791       if (!within_unsigned_range (fraction_bits, IMM6_BITS))
3792 	{
3793 	  as_bad (_("fraction bits value out of range"));
3794 	  return NULL;
3795 	}
3796       insn->bits |= ((fraction_bits & IMM6_MASK) << 8);
3797     }
3798 
3799   if (insn->fpu_width == FPU_WIDTH_PAIR)
3800     insn->bits |= (1 << 6);
3801 
3802   insn->len = 4;
3803   return l;
3804 }
3805 
3806 /* Parse an FPU basic arithmetic instruction.  */
3807 static const char *
parse_fbarith(const char * line,metag_insn * insn,const insn_template * template)3808 parse_fbarith (const char *line, metag_insn *insn,
3809 	       const insn_template *template)
3810 {
3811   const char *l = line;
3812   const metag_reg *regs[3];
3813 
3814   l = parse_fpu_regs (l, regs, 3);
3815 
3816   if (l == NULL)
3817     return NULL;
3818 
3819   insn->bits = (template->meta_opcode |
3820 		(regs[0]->no << 19) |
3821 		(regs[1]->no << 14) |
3822 		(regs[2]->no << 9));
3823 
3824   if (insn->fpu_width == FPU_WIDTH_PAIR)
3825     insn->bits |= (1 << 6);
3826   else if (insn->fpu_width == FPU_WIDTH_DOUBLE)
3827     insn->bits |= (1 << 5);
3828 
3829   if (insn->fpu_action_flags & FPU_ACTION_INV)
3830     insn->bits |= (1 << 7);
3831 
3832   insn->len = 4;
3833   return l;
3834 }
3835 
3836 /* Parse a floating point accumulator name.  */
3837 static const char *
parse_acf(const char * line,int * part)3838 parse_acf (const char *line, int *part)
3839 {
3840   const char *l = line;
3841   size_t i;
3842 
3843   for (i = 0; i < sizeof(metag_acftab)/sizeof(metag_acftab[0]); i++)
3844     {
3845       const metag_acf *acf = &metag_acftab[i];
3846       size_t name_len = strlen (acf->name);
3847 
3848       if (strncasecmp (l, acf->name, name_len) == 0)
3849 	{
3850 	  l += name_len;
3851 	  *part = acf->part;
3852 	  return l;
3853 	}
3854     }
3855   return NULL;
3856 }
3857 
3858 /* Parse an FPU extended arithmetic instruction.  */
3859 static const char *
parse_fearith(const char * line,metag_insn * insn,const insn_template * template)3860 parse_fearith (const char *line, metag_insn *insn,
3861 	       const insn_template *template)
3862 {
3863   const char *l = line;
3864   const metag_reg *regs[3];
3865   bool is_muz = (MINOR_OPCODE (template->meta_opcode) == 0x6
3866 		 && ((template->meta_opcode >> 4) & 0x1) != 0);
3867   bool is_o3o = (template->meta_opcode & 0x1) != 0;
3868   bool is_mac = 0;
3869   bool is_maw = 0;
3870 
3871   if (!strncasecmp (template->name, "MAW", 3))
3872     is_maw = 1;
3873 
3874   if (!strncasecmp (template->name, "MAC", 3))
3875     {
3876       int part;
3877       l = parse_acf (l, &part);
3878 
3879       if (l == NULL || part != 0)
3880 	return NULL;
3881 
3882       l = skip_comma (l);
3883 
3884       l = parse_fpu_regs (l, &regs[1], 2);
3885 
3886       is_mac = 1;
3887     }
3888   else
3889     {
3890       if (is_o3o && is_maw)
3891 	l = parse_fpu_regs (l, regs, 2);
3892       else
3893 	l = parse_fpu_regs (l, regs, 3);
3894     }
3895 
3896   if (l == NULL)
3897     return NULL;
3898 
3899   if (is_o3o && is_maw)
3900     insn->bits = (template->meta_opcode |
3901 		  (regs[1]->no << 9));
3902   else
3903     insn->bits = (template->meta_opcode |
3904 		  (regs[1]->no << 14));
3905 
3906   if (!(is_o3o && is_maw))
3907     insn->bits |= (regs[2]->no << 9);
3908 
3909   if (is_o3o && is_maw)
3910     insn->bits |= (regs[0]->no << 14);
3911   else if (!is_mac)
3912     insn->bits |= (regs[0]->no << 19);
3913 
3914   if (insn->fpu_width == FPU_WIDTH_PAIR)
3915     insn->bits |= (1 << 6);
3916   else if (insn->fpu_width == FPU_WIDTH_DOUBLE)
3917     insn->bits |= (1 << 5);
3918 
3919   if (!is_mac && !is_maw)
3920     if (insn->fpu_action_flags & FPU_ACTION_INV)
3921       insn->bits |= (1 << 7);
3922 
3923   if (is_muz)
3924     if (insn->fpu_action_flags & FPU_ACTION_QUIET)
3925       insn->bits |= (1 << 1);
3926 
3927   insn->len = 4;
3928   return l;
3929 }
3930 
3931 /* Parse an FPU RCP or RSQ instruction.  */
3932 static const char *
parse_frec(const char * line,metag_insn * insn,const insn_template * template)3933 parse_frec (const char *line, metag_insn *insn,
3934 	    const insn_template *template)
3935 {
3936   const char *l = line;
3937   const metag_reg *regs[2];
3938 
3939   l = parse_fpu_regs (l, regs, 2);
3940 
3941   if (l == NULL)
3942     return NULL;
3943 
3944   insn->bits = (template->meta_opcode |
3945 		(regs[0]->no << 19) |
3946 		(regs[1]->no << 14));
3947 
3948   if (insn->fpu_width == FPU_WIDTH_PAIR)
3949     insn->bits |= (1 << 6);
3950   else if (insn->fpu_width == FPU_WIDTH_DOUBLE)
3951     insn->bits |= (1 << 5);
3952 
3953   if (insn->fpu_action_flags & FPU_ACTION_ZERO)
3954     insn->bits |= (1 << 10);
3955   else if (insn->fpu_action_flags & FPU_ACTION_QUIET)
3956     insn->bits |= (1 << 9);
3957 
3958   if (insn->fpu_action_flags & FPU_ACTION_INV)
3959     insn->bits |= (1 << 7);
3960 
3961   insn->len = 4;
3962   return l;
3963 }
3964 
3965 /* Parse an FPU vector arithmetic instruction.  */
3966 static const char *
parse_fsimd(const char * line,metag_insn * insn,const insn_template * template)3967 parse_fsimd (const char *line, metag_insn *insn,
3968 	     const insn_template *template)
3969 {
3970   const char *l = line;
3971   const metag_reg *regs[3];
3972 
3973   if (insn->fpu_width != FPU_WIDTH_PAIR)
3974     {
3975       as_bad (_("simd instructions operate on pair values (L prefix)"));
3976       return NULL;
3977     }
3978 
3979   l = parse_fpu_regs (l, regs, 3);
3980 
3981   if (l == NULL)
3982     return NULL;
3983 
3984   if (regs[0]->no % 2)
3985     {
3986       as_bad (_("destination register should be even numbered"));
3987       return NULL;
3988     }
3989 
3990   if ((regs[1]->no % 2) ||
3991       (regs[2]->no % 2))
3992     {
3993       as_bad (_("source registers should be even numbered"));
3994       return NULL;
3995     }
3996 
3997   insn->bits = (template->meta_opcode |
3998 		(regs[0]->no << 19) |
3999 		(regs[1]->no << 14) |
4000 		(regs[2]->no << 9));
4001 
4002   if (insn->fpu_action_flags & FPU_ACTION_INV)
4003     insn->bits |= (1 << 7);
4004 
4005   insn->len = 4;
4006   return l;
4007 }
4008 
4009 /* Parse an FPU accumulator GET or SET instruction. */
4010 static const char *
parse_fget_set_acf(const char * line,metag_insn * insn,const insn_template * template)4011 parse_fget_set_acf (const char *line, metag_insn *insn,
4012 		    const insn_template *template)
4013 {
4014   const char *l = line;
4015   int part;
4016   metag_addr addr;
4017   bool is_get = MAJOR_OPCODE (template->meta_opcode) == OPC_GET;
4018 
4019   memset(&addr, 0, sizeof(addr));
4020   addr.reloc_type = BFD_RELOC_UNUSED;
4021 
4022   if (is_get)
4023     {
4024       l = parse_acf (l, &part);
4025 
4026       l = skip_comma (l);
4027 
4028       if (l == NULL)
4029 	return NULL;
4030 
4031       l = parse_mget_mset_addr (l, &addr);
4032     }
4033   else
4034     {
4035       l = parse_mget_mset_addr (l, &addr);
4036 
4037       l = skip_comma (l);
4038 
4039       if (l == NULL)
4040 	return NULL;
4041 
4042       l = parse_acf (l, &part);
4043     }
4044 
4045   if (l == NULL)
4046     return NULL;
4047 
4048   insn->bits = (template->meta_opcode |
4049 		(part << 19));
4050 
4051   if (!is_short_unit (addr.base_reg->unit))
4052     {
4053       as_bad (_("base unit must be one of %s"), SHORT_UNITS);
4054       return NULL;
4055     }
4056 
4057   insn->bits |= ((addr.base_reg->no << 14) |
4058 		 ((addr.base_reg->unit & SHORT_UNIT_MASK) << 5));
4059 
4060   insn->len = 4;
4061   return l;
4062 }
4063 
4064 /* Copy the name of the next register in LINE to REG_BUF.  */
4065 static size_t
strip_reg_name(const char * line,char * reg_buf)4066 strip_reg_name(const char *line, char *reg_buf)
4067 {
4068   const char *l = line;
4069   size_t len = 0;
4070 
4071   while (is_register_char (*l))
4072     {
4073       reg_buf[len] = *l;
4074       l++;
4075       len++;
4076       if (!(len < MAX_REG_LEN))
4077 	return 0;
4078     }
4079 
4080   if (len)
4081     reg_buf[len] = '\0';
4082 
4083   return len;
4084 }
4085 
4086 /* Parse a DSP register from LINE into REG using only the registers
4087    from DSP_REGTAB. Return the next character or NULL.  */
4088 static const char *
__parse_dsp_reg(const char * line,const metag_reg ** reg,htab_t dsp_regtab)4089 __parse_dsp_reg (const char *line, const metag_reg **reg, htab_t dsp_regtab)
4090 {
4091   const char *l = line;
4092   char name[MAX_REG_LEN];
4093   size_t len = 0;
4094   metag_reg entry;
4095   const metag_reg *_reg;
4096 
4097   /* We don't entirely strip the register name because we might
4098      actually want to match whole string in the register table,
4099      e.g. "D0AW.1++" not just "D0AW.1". The string length of the table
4100      entry limits our comparison to a reasonable bound anyway.  */
4101   while (is_register_char (*l) || *l == PLUS)
4102     {
4103       name[len] = *l;
4104       l++;
4105       len++;
4106       if (!(len < MAX_REG_LEN))
4107 	return NULL;
4108     }
4109 
4110   if (!len)
4111     return NULL;
4112 
4113   name[len] = '\0';
4114   entry.name = name;
4115 
4116   _reg = (const metag_reg *) htab_find (dsp_regtab, &entry);
4117   if (!_reg)
4118     return NULL;
4119 
4120   *reg = _reg;
4121 
4122   return l;
4123 }
4124 
4125 /* Parse a DSP register and setup "reg" with a metag_reg whose "no"
4126    member is suitable for encoding into a DSP insn register field.  */
4127 static const char *
parse_dsp_insn_reg(const char * line,const metag_reg ** reg)4128 parse_dsp_insn_reg (const char *line, const metag_reg **reg)
4129 {
4130   return __parse_dsp_reg (line, reg, dsp_reg_htab);
4131 }
4132 
4133 /* Parse a DSP register and setup "reg" with a metag_reg whose "no"
4134    member is suitable for encoding into a DSP template definition insn
4135    register field.
4136 
4137    There is a separate table for whether we're doing a load or a store
4138    definition. "load" specifies which table to look at.  */
4139 static const char *
parse_dsp_template_reg(const char * line,const metag_reg ** reg,bool load)4140 parse_dsp_template_reg (const char *line, const metag_reg **reg,
4141 			bool load)
4142 {
4143   return __parse_dsp_reg (line, reg, dsp_tmpl_reg_htab[load]);
4144 }
4145 
4146 /* Parse a single DSP register from LINE.  */
4147 static const char *
parse_dsp_reg(const char * line,const metag_reg ** reg,bool tmpl,bool load)4148 parse_dsp_reg (const char *line, const metag_reg **reg,
4149 	       bool tmpl, bool load)
4150 {
4151   if (tmpl)
4152     return parse_dsp_template_reg (line, reg, load);
4153   else
4154     return parse_dsp_insn_reg (line, reg);
4155 }
4156 
4157 /* Return TRUE if UNIT is an address unit.  */
4158 static bool
is_addr_unit(enum metag_unit unit)4159 is_addr_unit (enum metag_unit unit)
4160 {
4161   switch (unit)
4162     {
4163     case UNIT_A0:
4164     case UNIT_A1:
4165       return true;
4166     default:
4167       return false;
4168     }
4169 }
4170 
4171 /* Return TRUE if UNIT1 and UNIT2 are equivalent units.  */
4172 static bool
is_same_data_unit(enum metag_unit unit1,enum metag_unit unit2)4173 is_same_data_unit (enum metag_unit unit1, enum metag_unit unit2)
4174 {
4175   if (unit1 == unit2)
4176     return true;
4177 
4178   switch (unit1)
4179     {
4180     case UNIT_D0:
4181       if (unit2 == UNIT_ACC_D0 || unit2 == UNIT_RAM_D0)
4182 	return true;
4183       break;
4184     case UNIT_D1:
4185       if (unit2 == UNIT_ACC_D1 || unit2 == UNIT_RAM_D1)
4186 	return true;
4187       break;
4188     case UNIT_ACC_D0:
4189       if (unit2 == UNIT_D0 || unit2 == UNIT_RAM_D0)
4190 	return true;
4191       break;
4192     case UNIT_ACC_D1:
4193       if (unit2 == UNIT_D1 || unit2 == UNIT_RAM_D1)
4194 	return true;
4195       break;
4196     case UNIT_RAM_D0:
4197       if (unit2 == UNIT_ACC_D0 || unit2 == UNIT_D0)
4198 	return true;
4199       break;
4200     case UNIT_RAM_D1:
4201       if (unit2 == UNIT_ACC_D1 || unit2 == UNIT_D1)
4202 	return true;
4203       break;
4204     default:
4205       return false;
4206     }
4207 
4208   return false;
4209 }
4210 
4211 /* Return TRUE if the register NUM is a quickrot control register.  */
4212 static bool
is_quickrot_reg(unsigned int num)4213 is_quickrot_reg (unsigned int num)
4214 {
4215   switch (num)
4216     {
4217     case 2:
4218     case 3:
4219       return true;
4220     }
4221 
4222   return false;
4223 }
4224 
4225 /* Return TRUE if REG is an accumulator register.  */
4226 static bool
is_accumulator_reg(const metag_reg * reg)4227 is_accumulator_reg (const metag_reg *reg)
4228 {
4229   if (reg->unit == UNIT_ACC_D0 || reg->unit == UNIT_ACC_D1)
4230     return true;
4231 
4232   return false;
4233 }
4234 
4235 /* Return TRUE if REG is a DSP RAM register.  */
4236 static bool
is_dspram_reg(const metag_reg * reg)4237 is_dspram_reg (const metag_reg *reg)
4238 {
4239   if (reg->unit == UNIT_RAM_D0 || reg->unit == UNIT_RAM_D1)
4240       return true;
4241 
4242   return false;
4243 }
4244 
4245 static const char *
__parse_gp_reg(const char * line,const metag_reg ** reg,bool load)4246 __parse_gp_reg (const char *line, const metag_reg **reg, bool load)
4247 {
4248   const char *l = line;
4249   char reg_buf[MAX_REG_LEN];
4250   size_t len = 0;
4251 
4252   if (l == NULL)
4253     return NULL;
4254 
4255   /* Parse [DSPRAM.x].  */
4256   if (*l == ADDR_BEGIN_CHAR)
4257     {
4258       l++;
4259 
4260       if (l == NULL)
4261 	return NULL;
4262 
4263       l = parse_dsp_reg (l, reg, true, load);
4264       if (l == NULL)
4265 	return NULL;
4266 
4267       if (*l == ADDR_END_CHAR)
4268 	l++;
4269       else
4270 	{
4271 	  as_bad (_("expected ']', not %c in %s"), *l, l);
4272 	  return NULL;
4273 	}
4274 
4275       return l;
4276     }
4277   else
4278     {
4279 
4280       len = strip_reg_name (l, reg_buf);
4281       if (!len)
4282 	return NULL;
4283 
4284       l += len;
4285       *reg = parse_gp_reg (reg_buf);
4286       if (*reg == NULL)
4287 	return NULL;
4288     }
4289 
4290   return l;
4291 }
4292 
4293 /* Parse a list of DSP/GP registers. TRY_GP indicates whether we
4294    should try to parse the register as a general-purpose register if
4295    we fail to parse it as a DSP one. TMPL indicates whether the
4296    registers are part of a template definition instruction. If this is
4297    a template definition instruction LOAD says whether it's a load
4298    template insn. FIRST_DST indicates whether the first register is
4299    a destination operand.  */
4300 static const char *
parse_dsp_regs_list(const char * line,const metag_reg ** regs,size_t count,size_t * regs_read,bool try_gp,bool tmpl,bool load,bool first_dst)4301 parse_dsp_regs_list (const char *line, const metag_reg **regs, size_t count,
4302 		     size_t *regs_read, bool try_gp, bool tmpl,
4303 		     bool load, bool first_dst)
4304 {
4305   const char *l = line;
4306   int seen_regs = 0;
4307   size_t i;
4308   const metag_reg *reg;
4309 
4310   for (i = 0; i < count; i++)
4311     {
4312       const char *next, *ll;
4313 
4314       next = l;
4315 
4316       if (i > 0)
4317 	{
4318 	  l = skip_comma (l);
4319 	  if (l == NULL)
4320 	    {
4321 	      *regs_read = seen_regs;
4322 	      return next;
4323 	    }
4324 	}
4325 
4326       ll = parse_dsp_reg (l, &reg, tmpl, load);
4327 
4328       if (!ll)
4329 	{
4330 	  if (try_gp)
4331 	    {
4332 	      l = __parse_gp_reg (l, &reg, !(first_dst && i == 0));
4333 	      if (l == NULL)
4334 		{
4335 		  *regs_read = seen_regs;
4336 		  return next;
4337 		}
4338 	      regs[i] = reg;
4339 	      seen_regs++;
4340 	    }
4341 	  else
4342 	    {
4343 	      *regs_read = seen_regs;
4344 	      return l;
4345 	    }
4346 	}
4347       else
4348 	{
4349 	  regs[i] = reg;
4350 	  seen_regs++;
4351 	  l = ll;
4352 	}
4353     }
4354 
4355   *regs_read = seen_regs;
4356   return l;
4357 }
4358 
4359 /* Parse the following memory references:
4360 
4361      - [Ax.r]
4362      - [Ax.r++]
4363      - [Ax.r--]
4364      - [Ax.r+Ax.r++]
4365      - [Ax.r-Ax.r--]
4366 
4367      - [DSPRam]
4368      - [DSPRam++]
4369      - [DSPRam+DSPRam++]
4370      - [DSPRam-DSPRam--]  */
4371 static const char *
parse_dsp_addr(const char * line,metag_addr * addr,unsigned int size,bool load)4372 parse_dsp_addr (const char *line, metag_addr *addr, unsigned int size,
4373 		bool load)
4374 {
4375   const char *l = line, *ll;
4376   const metag_reg *regs[1];
4377   size_t regs_read;
4378 
4379   /* Skip opening square bracket.  */
4380   l++;
4381 
4382   l = parse_dsp_regs_list (l, regs, 1, &regs_read, true, true, load, false);
4383 
4384   if (l == NULL)
4385     return NULL;
4386 
4387   if (!is_addr_unit (regs[0]->unit) &&
4388       !is_dspram_reg (regs[0]))
4389     {
4390       as_bad (_("invalid register for memory access"));
4391       return NULL;
4392     }
4393 
4394   addr->base_reg = regs[0];
4395 
4396   if (*l == ADDR_END_CHAR)
4397     {
4398       addr->exp.X_op = O_constant;
4399       addr->exp.X_add_symbol = NULL;
4400       addr->exp.X_op_symbol = NULL;
4401 
4402       /* Simple register with no offset (0 immediate).  */
4403       addr->exp.X_add_number = 0;
4404 
4405       addr->immediate = 1;
4406       l++;
4407 
4408       return l;
4409     }
4410 
4411   ll = parse_addr_post_incr_op (l, addr);
4412 
4413   if (ll && *ll == ADDR_END_CHAR)
4414     {
4415       if (addr->update == 1)
4416 	{
4417 	  /* We have a post increment/decrement.  */
4418 	  addr->exp.X_op = O_constant;
4419 	  addr->exp.X_add_number = size;
4420 	  addr->exp.X_add_symbol = NULL;
4421 	  addr->exp.X_op_symbol = NULL;
4422 	  addr->post_increment = 1;
4423 	}
4424       addr->immediate = 1;
4425       ll++;
4426       return ll;
4427     }
4428 
4429   addr->post_increment = 0;
4430 
4431   l = parse_addr_op (l, addr);
4432 
4433   if (l == NULL)
4434     return NULL;
4435 
4436   l = parse_dsp_regs_list (l, regs, 1, &regs_read, true, true, load, false);
4437 
4438   if (l == NULL)
4439     return NULL;
4440 
4441   if (regs[0]->unit != addr->base_reg->unit)
4442     {
4443       as_bad (_("offset and base must be from the same unit"));
4444       return NULL;
4445     }
4446 
4447   addr->offset_reg = regs[0];
4448 
4449   if (*l == ADDR_END_CHAR)
4450     {
4451       l++;
4452       return l;
4453     }
4454 
4455   l = parse_addr_post_incr_op (l, addr);
4456 
4457   if (l == NULL)
4458     return NULL;
4459 
4460   if (*l == ADDR_END_CHAR)
4461     {
4462       l++;
4463       return l;
4464     }
4465 
4466   return NULL;
4467 }
4468 
4469 /* Parse a DSP GET or SET instruction.  */
4470 static const char *
parse_dget_set(const char * line,metag_insn * insn,const insn_template * template)4471 parse_dget_set (const char *line, metag_insn *insn,
4472 		const insn_template *template)
4473 {
4474   const char *l = line;
4475   metag_addr addr;
4476   int unit = 0;
4477   int rd_reg = 0;
4478   bool is_get = (template->meta_opcode & 0x100) != 0;
4479   bool is_dual = (template->meta_opcode & 0x4) != 0;
4480   bool is_template = false;
4481   const metag_reg *regs[2];
4482   unsigned int size;
4483   size_t count, regs_read;
4484 
4485   memset(&addr, 0, sizeof(addr));
4486   addr.reloc_type = BFD_RELOC_UNUSED;
4487 
4488   size = is_dual ? 8 : 4;
4489   count = is_dual ? 2 : 1;
4490 
4491   if (is_get)
4492     {
4493       /* GETL can be used on one template table entry.  */
4494       if (*l == 'T')
4495 	count = 1;
4496 
4497       l = parse_dsp_regs_list (l, regs, count, &regs_read, false,
4498 			       false, false, false);
4499       l = skip_comma (l);
4500 
4501       if (l == NULL)
4502 	{
4503 	  as_bad (_("unexpected end of line"));
4504 	  return NULL;
4505 	}
4506 
4507       l = parse_addr (l, &addr, size);
4508     }
4509   else
4510     {
4511       l = parse_addr (l, &addr, size);
4512 
4513       l = skip_comma (l);
4514 
4515       if (l == NULL)
4516 	return NULL;
4517 
4518       /* GETL can be used on one template table entry.  */
4519       if (*l == 'T')
4520 	count = 1;
4521 
4522       l = parse_dsp_regs_list (l, regs, count, &regs_read, false, false,
4523 			       false, false);
4524     }
4525 
4526   if (l == NULL)
4527     return NULL;
4528 
4529   /* The first register dictates the unit.  */
4530   if (regs[0]->unit == UNIT_DT)
4531       is_template = true;
4532   else
4533     {
4534       if (regs[0]->unit == UNIT_D0 || regs[0]->unit == UNIT_RAM_D0 ||
4535 	  regs[0]->unit == UNIT_ACC_D0)
4536 	unit = 0;
4537       else
4538 	unit = 1;
4539     }
4540 
4541   rd_reg = regs[0]->no;
4542 
4543   /* The 'H' modifier allows a DSP GET/SET instruction to target the
4544      upper 8-bits of an accumulator. It is _only_ valid for the
4545      accumulators.  */
4546   if (insn->dsp_daoppame_flags & DSP_DAOPPAME_HIGH)
4547     {
4548       if (is_template || !(rd_reg >= 16 && rd_reg < 20))
4549 	{
4550 	  as_bad (_("'H' modifier only valid for accumulator registers"));
4551 	  return NULL;
4552 	}
4553 
4554       /* Top 8-bits of the accumulator.  */
4555       rd_reg |= 8;
4556     }
4557 
4558   if (is_template)
4559     {
4560       insn->bits = (template->meta_opcode | (1 << 1));
4561     }
4562   else
4563     {
4564       insn->bits = (template->meta_opcode | unit);
4565     }
4566 
4567   insn->bits |= (rd_reg << 19);
4568 
4569   if (addr.immediate)
4570     {
4571       int offset = addr.exp.X_add_number;
4572 
4573       if (addr.negate)
4574 	offset = -offset;
4575 
4576       offset = offset / (int)size;
4577 
4578       if (!within_signed_range (offset, DGET_SET_IMM_BITS))
4579 	{
4580 	  as_bad (_("offset value out of range"));
4581 	  return NULL;
4582 	}
4583 
4584       offset = offset & DGET_SET_IMM_MASK;
4585 
4586       insn->bits |= (1 << 13);
4587       insn->bits |= (offset << 9);
4588     }
4589   else
4590     {
4591       int au = (addr.base_reg->unit == UNIT_A1);
4592 
4593       insn->bits |= (au << 18);
4594       insn->bits |= ((addr.base_reg->no & REG_MASK) << 14);
4595       insn->bits |= ((addr.offset_reg->no & REG_MASK) << 9);
4596     }
4597 
4598   if (is_dual)
4599       insn->bits |= (1 << 2);
4600 
4601   if (!is_addr_unit (addr.base_reg->unit))
4602     {
4603       as_bad (_("base unit must be either A0 or A1"));
4604       return NULL;
4605     }
4606 
4607   unit = (addr.base_reg->unit == UNIT_A0) ? 0 : 1;
4608   insn->bits |= ((addr.base_reg->no << 14) | (unit << 18));
4609 
4610   insn->len = 4;
4611 
4612   return l;
4613 }
4614 
4615 /* Parse a DSP template instruction.  */
4616 static const char *
parse_dtemplate(const char * line,metag_insn * insn,const insn_template * template)4617 parse_dtemplate (const char *line, metag_insn *insn,
4618 		 const insn_template *template)
4619 {
4620   const char *l = line;
4621   const metag_reg *regs[TEMPLATE_NUM_REGS];
4622   bool daop_only = false;
4623   int regs_val[4];
4624   int regs_which[4] = { -1, -1, -1, -1};	/* Register or immediate?  */
4625   int i;
4626 
4627   for (i = 0; i < TEMPLATE_NUM_REGS; i++)
4628     {
4629       if (l == NULL)
4630 	{
4631 	  as_bad (_("unexpected end of line"));
4632 	  return NULL;
4633 	}
4634 
4635       /* We may only have 3 register operands.  */
4636       if (*l == END_OF_INSN && i == 3)
4637 	{
4638 	  daop_only = true;
4639 	  break;
4640 	}
4641 
4642       if (i != 0)
4643 	{
4644 	  l = skip_comma (l);
4645 	  if (l == NULL)
4646 	    return NULL;
4647 	}
4648 
4649       if (*l == IMM_CHAR)
4650 	{
4651 	  l = parse_imm_constant (l, insn, &regs_val[i]);
4652 	  if (l == NULL)
4653 	    {
4654 	      as_bad (_("invalid immediate"));
4655 	      return NULL;
4656 	    }
4657 	  regs_which[i] = 0;
4658 	}
4659       else
4660 	{
4661 	  /* We can't tell from the template instantiation whether
4662 	     this is a load or store. So we have to try looking up the
4663 	     register name in both the load and store tables.  */
4664 	  const char *l2 = l;
4665 	  l = __parse_gp_reg (l, &regs[i], true);
4666 	  if (l == NULL)
4667 	    {
4668 	      /* Try the store table too.  */
4669 	      l = __parse_gp_reg (l2, &regs[i], false);
4670 	      if (l == NULL)
4671 		{
4672 		  /* Then try a DSP register.  */
4673 		  l = parse_dsp_insn_reg (l2, &regs[i]);
4674 		  if (l == NULL || regs[i]->unit == UNIT_DT)
4675 		    {
4676 		      as_bad (_("invalid register"));
4677 		      return NULL;
4678 		    }
4679 		}
4680 	    }
4681 	  regs_which[i] = 1;
4682 	}
4683     }
4684 
4685   insn->bits = template->meta_opcode;
4686 
4687   if (regs_which[0] == 0)
4688     insn->bits |= (regs_val[0] << 19);
4689   else if (regs_which[0] == 1)
4690     insn->bits |= (regs[0]->no << 19);
4691 
4692   if (regs_which[1] == 0)
4693     insn->bits |= (regs_val[1] << 14);
4694   else if (regs_which[1] == 1)
4695     insn->bits |= (regs[1]->no << 14);
4696 
4697   if (regs_which[2] == 0)
4698     insn->bits |= (regs_val[2] << 9);
4699   else if (regs_which[2] == 1)
4700     insn->bits |= (regs[2]->no << 9);
4701 
4702   if (regs_which[3] == 0)
4703     insn->bits |= (regs_val[3] << 4);
4704   else if (regs_which[3] == 1)
4705     insn->bits |= (regs[3]->no << 4);
4706 
4707   /* DaOp only.  */
4708   if (daop_only)
4709     insn->bits |= (0x3 << 24); /* Set the minor opcode.  */
4710   else if (insn->dsp_daoppame_flags & DSP_DAOPPAME_HIGH) /* Half Load/Store.  */
4711     insn->bits |= (0x5 << 24); /* Set the minor opcode.  */
4712 
4713   insn->len = 4;
4714 
4715   return l;
4716 }
4717 
4718 /* Parse a DSP Template definition memory reference, e.g
4719    [A0.7+A0.5++]. DSPRAM is set to true by this function if this
4720    template definition is a DSP RAM template definition.  */
4721 static const char *
template_mem_ref(const char * line,metag_addr * addr,bool * dspram,int size,bool load)4722 template_mem_ref(const char *line, metag_addr *addr,
4723 		 bool *dspram, int size, bool load)
4724 {
4725   const char *l = line;
4726 
4727   l = parse_dsp_addr (l, addr, size, load);
4728 
4729   if (l != NULL)
4730     {
4731       if (is_addr_unit(addr->base_reg->unit))
4732 	*dspram = false;
4733       else
4734 	*dspram = true;
4735     }
4736 
4737   return l;
4738 }
4739 
4740 /* Sets LOAD to TRUE if this is a Template load definition (otherwise
4741    it's a store). Fills out ADDR, TEMPLATE_REG and ADDR_UNIT.  */
4742 static const char *
parse_template_regs(const char * line,bool * load,unsigned int * addr_unit,const metag_reg ** template_reg,metag_addr * addr,bool * dspram,int size)4743 parse_template_regs (const char *line, bool *load,
4744 		     unsigned int *addr_unit,
4745 		     const metag_reg **template_reg, metag_addr *addr,
4746 		     bool *dspram, int size)
4747 {
4748   const char *l = line;
4749 
4750   if (l == NULL)
4751     return NULL;
4752 
4753   /* DSP Template load definition (Tx, [Ax]) */
4754   if (*l == 'T')
4755     {
4756       *load = true;
4757       l = parse_dsp_reg (l, &template_reg[0], false, false);
4758       if (l == NULL)
4759 	return NULL;
4760 
4761       l = skip_comma (l);
4762 
4763       l = template_mem_ref (l, addr, dspram, size, *load);
4764 
4765       if (addr->base_reg->unit == UNIT_A1)
4766 	*addr_unit = 1;
4767 
4768     }
4769   else if (*l == ADDR_BEGIN_CHAR) /* DSP Template store ([Ax], Tx) */
4770     {
4771       *load = false;
4772       l = template_mem_ref (l, addr, dspram, size, *load);
4773       l = skip_comma(l);
4774 
4775       if (l == NULL)
4776 	return NULL;
4777 
4778       l = parse_dsp_reg (l, &template_reg[0], false, false);
4779       if (l == NULL)
4780 	return NULL;
4781 
4782       if (addr->base_reg->unit == UNIT_A1)
4783 	*addr_unit = 1;
4784     }
4785   else
4786     {
4787       as_bad (_("invalid register operand"));
4788       return NULL;
4789     }
4790 
4791   return l;
4792 }
4793 
4794 #define INVALID_SHIFT (-1)
4795 
4796 static metag_reg _reg;
4797 
4798 /* Parse a template instruction definition.  */
4799 static const char *
interpret_template_regs(const char * line,metag_insn * insn,const metag_reg ** regs,int * regs_shift,bool * load,bool * dspram,int size,int * ls_shift,int * au_shift,unsigned int * au,int * imm,int * imm_shift,unsigned int * imm_mask)4800 interpret_template_regs(const char *line, metag_insn *insn,
4801 			const metag_reg **regs,
4802 			int *regs_shift, bool *load, bool *dspram,
4803 			int size, int *ls_shift, int *au_shift,
4804 			unsigned int *au, int *imm, int *imm_shift,
4805 			unsigned int *imm_mask)
4806 {
4807   const char *l = line;
4808   metag_addr addr;
4809   const metag_reg *template_reg[1];
4810 
4811   memset (&addr, 0, sizeof(addr));
4812 
4813   regs_shift[0] = 19;
4814   regs_shift[1] = INVALID_SHIFT;
4815 
4816   insn->bits |= (1 << 1);
4817 
4818   l = skip_whitespace (l);
4819 
4820   l = parse_template_regs (l, load, au, template_reg,
4821 			   &addr, dspram, size);
4822   if (l == NULL)
4823     {
4824       as_bad (_("could not parse template definition"));
4825       return NULL;
4826     }
4827 
4828   regs[2] = template_reg[0];
4829   regs_shift[2] = 9;
4830 
4831   /* DSPRAM definition.  */
4832   if (*dspram)
4833     {
4834 
4835       _reg = *addr.base_reg;
4836 
4837       if (addr.immediate)
4838 	{
4839 	  /* Set the post-increment bit in the register field.  */
4840 	  if (addr.update)
4841 	    _reg.no |= 0x1;
4842 	}
4843       else
4844 	{
4845 	  /* The bottom bit of the increment register tells us
4846 	     whether it's increment register 0 or 1.  */
4847 	  if (addr.offset_reg->no & 0x1)
4848 	    _reg.no |= 0x3;
4849 	  else
4850 	    _reg.no |= 0x2;
4851 	}
4852 
4853       regs[0] = &_reg;
4854 
4855       insn->bits |= (0x3 << 17); /* This signifies a DSPRAM definition.  */
4856     }
4857   else /* DaOpPaMe definition.  */
4858     {
4859       regs[0] = addr.base_reg;
4860       if (addr.immediate)
4861 	{
4862 	  /* Set the I bit.  */
4863 	  insn->bits |= (1 << 18);
4864 
4865 	  if (addr.update == 1)
4866 	    {
4867 	      if (addr.negate == 1)
4868 		*imm = 0x3;
4869 	      else
4870 		*imm = 0x1;
4871 	    }
4872 
4873 	  *imm_shift = 14;
4874 	  *imm_mask = 0x3;
4875 	}
4876       else
4877 	{
4878 	  /* Setup the offset register.  */
4879 	  regs[1] = addr.offset_reg;
4880 	  regs_shift[1] = 14;
4881 	}
4882       *au_shift = 23;
4883     }
4884 
4885   *ls_shift = 13;
4886 
4887   return l;
4888 }
4889 
4890 /* Does this combination of units need the O2R bit and can it be encoded?  */
4891 static bool
units_need_o2r(enum metag_unit unit1,enum metag_unit unit2)4892 units_need_o2r (enum metag_unit unit1, enum metag_unit unit2)
4893 {
4894   if (unit1 == unit2)
4895     return false;
4896 
4897   if (unit1 == UNIT_D0 || unit1 == UNIT_ACC_D0 || unit1 == UNIT_RAM_D0)
4898     {
4899       if (unit2 == UNIT_ACC_D0 || unit2 == UNIT_RAM_D0 || unit2 == UNIT_D0)
4900 	return false;
4901 
4902       switch (unit2)
4903 	{
4904 	case UNIT_A1:
4905 	case UNIT_D1:
4906 	case UNIT_RD:
4907 	case UNIT_A0:
4908 	  return true;
4909 	default:
4910 	  return false;
4911 	}
4912     }
4913 
4914   if (unit1 == UNIT_D1 || unit1 == UNIT_ACC_D1 || unit1 == UNIT_RAM_D1)
4915     {
4916       if (unit2 == UNIT_ACC_D1 || unit2 == UNIT_RAM_D1 || unit2 == UNIT_D1)
4917 	return false;
4918 
4919       switch (unit2)
4920 	{
4921 	case UNIT_A1:
4922 	case UNIT_D0:
4923 	case UNIT_RD:
4924 	case UNIT_A0:
4925 	  return true;
4926 	default:
4927 	  return false;
4928 	}
4929     }
4930 
4931   return false;
4932 }
4933 
4934 /* Return TRUE if this is a DSP data unit.  */
4935 static bool
is_dsp_data_unit(const metag_reg * reg)4936 is_dsp_data_unit (const metag_reg *reg)
4937 {
4938   switch (reg->unit)
4939     {
4940     case UNIT_D0:
4941     case UNIT_D1:
4942     case UNIT_ACC_D0:
4943     case UNIT_ACC_D1:
4944     case UNIT_RAM_D0:
4945     case UNIT_RAM_D1:
4946       return true;
4947     default:
4948       return false;
4949     }
4950 }
4951 
4952 static metag_reg o2r_reg;
4953 
4954 /* Parse a DaOpPaMe load template definition.  */
4955 static const char *
parse_dalu(const char * line,metag_insn * insn,const insn_template * template)4956 parse_dalu (const char *line, metag_insn *insn,
4957 	    const insn_template *template)
4958 {
4959   const char *l = line;
4960   const char *ll;
4961   const metag_reg *regs[4];
4962   metag_addr addr;
4963   size_t regs_read;
4964   bool is_mov = MAJOR_OPCODE (template->meta_opcode) == OPC_ADD;
4965   bool is_cmp = (MAJOR_OPCODE (template->meta_opcode) == OPC_CMP
4966 		 && (template->meta_opcode & 0xee) == 0);
4967   bool is_dual = insn->dsp_width == DSP_WIDTH_DUAL;
4968   bool is_quickrot64 = (insn->dsp_action_flags & DSP_ACTION_QR64) != 0;
4969   int l1_shift = INVALID_SHIFT;
4970   bool load = false;
4971   int ls_shift = INVALID_SHIFT;
4972   bool ar = false;
4973   int ar_shift = INVALID_SHIFT;
4974   int regs_shift[3] = { INVALID_SHIFT, INVALID_SHIFT, INVALID_SHIFT };
4975   int imm = 0;
4976   int imm_shift = INVALID_SHIFT;
4977   unsigned int imm_mask = 0;
4978   unsigned int au = 0;
4979   int au_shift = INVALID_SHIFT;
4980   unsigned int du = 0;
4981   int du_shift = INVALID_SHIFT;
4982   unsigned int sc = ((insn->dsp_action_flags & DSP_ACTION_OV) != 0);
4983   int sc_shift = INVALID_SHIFT;
4984   unsigned int om = ((insn->dsp_action_flags & DSP_ACTION_MOD) != 0);
4985   int om_shift = INVALID_SHIFT;
4986   unsigned int o2r = 0;
4987   int o2r_shift = INVALID_SHIFT;
4988   unsigned int qr = 0;
4989   int qr_shift = INVALID_SHIFT;
4990   int qd_shift = INVALID_SHIFT;
4991   unsigned int qn = 0;
4992   int qn_shift = INVALID_SHIFT;
4993   unsigned int a1 = ((insn->dsp_action_flags & (DSP_ACTION_ACC_SUB|DSP_ACTION_ACC_ZERO)) != 0);
4994   int a1_shift = INVALID_SHIFT;
4995   unsigned int a2 = ((insn->dsp_action_flags & (DSP_ACTION_ACC_SUB|DSP_ACTION_ACC_ADD)) != 0);
4996   int a2_shift = INVALID_SHIFT;
4997   unsigned su = ((insn->dsp_action_flags & DSP_ACTION_UMUL) != 0);
4998   int su_shift = INVALID_SHIFT;
4999   unsigned int ac;
5000   int ac_shift = INVALID_SHIFT;
5001   unsigned int mx = (((insn->dsp_daoppame_flags & DSP_DAOPPAME_8) != 0) ||
5002 		     (insn->dsp_daoppame_flags & DSP_DAOPPAME_16) != 0);
5003   int mx_shift = INVALID_SHIFT;
5004   int size = is_dual ? 8 : 4;
5005   bool dspram;
5006   bool conditional = (MINOR_OPCODE (template->meta_opcode) & 0x4) != 0;
5007 
5008   /* XFIXME: check the flags are valid with the instruction.  */
5009   if (is_quickrot64 && !(template->arg_type & DSP_ARGS_QR))
5010     {
5011       as_bad (_("QUICKRoT 64-bit extension not applicable to this instruction"));
5012       return NULL;
5013     }
5014 
5015   insn->bits = template->meta_opcode;
5016 
5017   memset (regs, 0, sizeof (regs));
5018   memset (&addr, 0, sizeof (addr));
5019 
5020   /* There are the following forms of DSP ALU instructions,
5021 
5022    * Group 1:
5023       19. D[T]  Op    De.r,Dx.r,De.r
5024       1.  D[T]  Op    De.r,Dx.r,De.r|ACe.r	[Accumulator in src 2]
5025       3.  D[T]  Op    De.r,Dx.r,De.r[,Ae.r]	[QUICKRoT]
5026       2.  D[T]  Op    ACe.e,ACx.r,ACo.e		[cross-unit accumulator op]
5027       5.  D[T]  Op    De.r|ACe.r,Dx.r,De.r
5028       20. D[T]  Op    De.r,Dx.r|ACx.r,De.r
5029       8.  D     Opcc  De.r,Dx.r,Rx.r
5030       6.  D     Op    De.r,Dx.r,Rx.r|RD
5031       17. D     Op    De.r|ACe.r,Dx.r,Rx.r|RD
5032       7.  D     Op    De.e,Dx.r,#I16
5033 
5034    * Group 2:
5035       4.  D[T]  Op    Dx.r,De.r
5036       10. D     Op    Dx.r,Rx.r|RD
5037       13. D     Op    Dx.r,Rx.r
5038       11. D     Op    Dx.r,#I16
5039       12. D[T]  Op    De.r,Dx.r
5040       14. D     Op    DSPe.r,Dx.r
5041       15. D     Op    DSPx.r,#I16
5042       16. D     Op    De.r,DSPx.r
5043       18. D     Op    De.r,Dx.r|ACx.r
5044 
5045    * Group 3:
5046       22. D     Op    De.r,Dx.r|ACx.r,De.r|#I5
5047       23. D     Op    Ux.r,Dx.r|ACx.r,De.r|#I5
5048       21. D     Op    De.r,Dx.r|ACx.r,#I5  */
5049 
5050   /* Group 1.  */
5051   if (template->arg_type & DSP_ARGS_1)
5052     {
5053       du_shift = 24;
5054 
5055       /* Could this be a cross-unit accumulator op,
5056 	 e.g. ACe.e,ACx.r,ACo.e */
5057       if (template->arg_type & DSP_ARGS_XACC)
5058 	{
5059 	  ll = parse_dsp_regs_list (l, regs, 3, &regs_read, false, false,
5060 				    false, false);
5061 	  if (ll != NULL && regs_read == 3
5062 	      && is_accumulator_reg (regs[0]))
5063 	    {
5064 	      if (regs[0]->unit != regs[1]->unit ||
5065 		  regs[2]->unit == regs[1]->unit)
5066 		{
5067 		  as_bad (_("invalid operands for cross-unit op"));
5068 		  return NULL;
5069 		}
5070 
5071 	      du = (regs[1]->unit == UNIT_ACC_D1);
5072 	      regs_shift[1] = 19;
5073 	      l = ll;
5074 
5075 	      /* All cross-unit accumulator ops have bits 8 and 6 set.  */
5076 	      insn->bits |= (5 << 6);
5077 
5078 	      goto check_for_template;
5079 	    }
5080 
5081 	  /* If we reach here, this instruction is not a
5082 	     cross-unit accumulator op.  */
5083 	}
5084 
5085       if (template->arg_type & DSP_ARGS_SPLIT8)
5086 	om_shift = 7;
5087 
5088       sc_shift = 5;
5089       l1_shift = 4;
5090       o2r_shift = 0;
5091 
5092       /* De.r|ACe.r,Dx.r,De.r */
5093       if (template->arg_type & DSP_ARGS_DACC)
5094 	{
5095 	  /* XFIXME: these need moving?  */
5096 	  a2_shift = 7;
5097 	  su_shift = 6;
5098 	  a1_shift = 2;
5099 	  om_shift = 3;
5100 
5101 	  ll = parse_dsp_reg (l, &regs[0], false, false);
5102 	  if (ll != NULL)
5103 	    {
5104 	      /* Using ACe.r as the dst requires one of the P,N or Z
5105 		 flags to be used.  */
5106 	      if (!(insn->dsp_action_flags &
5107 		    (DSP_ACTION_ACC_SUB|DSP_ACTION_ACC_ADD|DSP_ACTION_ACC_ZERO)))
5108 		{
5109 		  as_bad (_("missing flags: one of 'P', 'N' or 'Z' required"));
5110 		  return NULL;
5111 		}
5112 
5113 	      l = ll;
5114 	      l = skip_comma (l);
5115 	      l = parse_dsp_regs_list (l, &regs[1], 2, &regs_read,
5116 				       true, false, false, false);
5117 	      if (l == NULL || regs_read != 2)
5118 		{
5119 		  as_bad (_("invalid register"));
5120 		  return NULL;
5121 		}
5122 
5123 	      if (regs[1]->unit == UNIT_D1 || regs[1]->unit == UNIT_RAM_D1)
5124 		du = 1;
5125 
5126 	      regs_shift[0] = 19;
5127 	      regs_shift[1] = 14;
5128 	      regs_shift[2] = 9;
5129 	      goto check_for_template;
5130 	    }
5131 
5132 	  /* If we reach here, this instruction does not use the
5133 	     accumulator as the destination register.  */
5134 	  if ((insn->dsp_action_flags &
5135 	       (DSP_ACTION_ACC_SUB|DSP_ACTION_ACC_ADD|DSP_ACTION_ACC_ZERO)))
5136 	    {
5137 	      as_bad (_("'P', 'N' or 'Z' flags may only be specified when accumulating"));
5138 	      return NULL;
5139 	    }
5140 	}
5141 
5142       regs_shift[0] = 19;
5143 
5144 
5145       l = parse_dsp_regs_list (l, regs, 2, &regs_read, true, false, false, true);
5146       if (l == NULL || regs_read != 2)
5147 	return NULL;
5148 
5149       l = skip_comma (l);
5150       if (l == NULL)
5151 	return NULL;
5152 
5153       if (regs[1]->unit == UNIT_D1 || regs[1]->unit == UNIT_RAM_D1)
5154 	du = 1;
5155 
5156       if (is_accumulator_reg(regs[0]) && !(template->arg_type & DSP_ARGS_DACC))
5157        {
5158 	 as_bad (_("accumulator not a valid destination"));
5159 	 return NULL;
5160        }
5161 
5162       /* Check for immediate, e.g. De.r,Dx.r,#I16 */
5163       if (*l == IMM_CHAR)
5164 	{
5165 	  l = parse_imm16 (l, insn, &imm);
5166 	  if (l == NULL)
5167 	    {
5168 	      as_bad (_("invalid immediate value"));
5169 	      return NULL;
5170 	    }
5171 
5172 	  if (!within_signed_range (imm, IMM16_BITS))
5173 	    {
5174 	      as_bad (_("immediate value out of range"));
5175 	      return NULL;
5176 	    }
5177 
5178 	  if (regs[0]->unit != regs[1]->unit || regs[0]->no != regs[1]->no)
5179 	    {
5180 	      as_bad (_("immediate value not allowed when source & dest differ"));
5181 	      return NULL;
5182 	    }
5183 
5184 	  imm_mask = 0xffff;
5185 	  imm_shift = 3;
5186 
5187 	  /* Set the I-bit */
5188 	  insn->bits |= (1 << 25);
5189 
5190 	  insn->bits |= (0x3 << 0);
5191 
5192 	  l1_shift = 2;
5193 
5194 	  /* Remove any bits that have been set in the immediate
5195 	     field.  */
5196 	  insn->bits &= ~(imm_mask << imm_shift);
5197 	}
5198       else
5199 	{
5200 
5201 	  regs_shift[1] = 14;
5202 	  regs_shift[2] = 9;
5203 
5204 	  /* Is Rs2 an accumulator reg, e.g. De.r,Dx.r,De.r|ACe.r */
5205 	  ll = parse_dsp_reg (l, &regs[2], false, false);
5206 	  if (ll != NULL)
5207 	    {
5208 	      l = ll;
5209 
5210 	      if (!(template->arg_type & DSP_ARGS_ACC2))
5211 		{
5212 		  as_bad (_("invalid register operand: %s"), regs[2]->name);
5213 		  return NULL;
5214 		}
5215 
5216 	      om_shift = 3;
5217 	      ar_shift = 7;
5218 	      ar = true;
5219 	    }
5220 	  else
5221 	    {
5222 	      /* De.r,Dx.r,De.r */
5223 	      l = __parse_gp_reg (l, &regs[2], true);
5224 	      if (l == NULL)
5225 		return NULL;
5226 	    }
5227 
5228 	  if (template->arg_type & DSP_ARGS_ACC2)
5229 	    om_shift = 3;
5230 
5231 	  /* Is this a QUICKRoT instruction? De.r,Dx.r,De.r[,Ae.r] */
5232 	  if (template->arg_type & DSP_ARGS_QR)
5233 	    {
5234 	      if (conditional)
5235 		qn_shift = 5;
5236 	      else
5237 		{
5238 		  qn_shift = 7;
5239 		  qr_shift = 6;
5240 		  qd_shift = 5;
5241 		}
5242 
5243 	      l = skip_comma (l);
5244 	      if (l == NULL)
5245 		{
5246 		  as_bad (_("QUICKRoT extension requires 4 registers"));
5247 		  return NULL;
5248 		}
5249 
5250 	      l = __parse_gp_reg (l, &regs[3], true);
5251 	      if (l == NULL)
5252 		{
5253 		  as_bad (_("invalid fourth register"));
5254 		  return NULL;
5255 		}
5256 
5257 	      if (!is_addr_unit (regs[3]->unit) ||
5258 		  !is_quickrot_reg (regs[3]->no))
5259 		{
5260 		  as_bad (_("A0.2,A0.3,A1.2,A1.3 required for QUICKRoT register"));
5261 		  return NULL;
5262 		}
5263 
5264 	      qn = (regs[3]->no == 3);
5265 	    }
5266 	}
5267 
5268     check_for_template:
5269       /* This is the common exit path. Check for o2r.  */
5270       if (regs[2] != NULL)
5271 	{
5272 	  o2r = units_need_o2r (regs[1]->unit, regs[2]->unit);
5273 	  if (o2r)
5274 	    {
5275 	      o2r_reg.no = lookup_o2r (0, du, regs[2]);
5276 	      o2r_reg.unit = regs[2]->unit;
5277 	      regs[2] = &o2r_reg;
5278 	    }
5279 	}
5280 
5281       /* Check any DSP RAM pointers are valid for this unit.  */
5282       if ((du && (regs[0]->unit == UNIT_RAM_D0)) ||
5283 	  (!du && (regs[0]->unit == UNIT_RAM_D1)) ||
5284 	  (du && (regs[1]->unit == UNIT_RAM_D0)) ||
5285 	  (!du && (regs[1]->unit == UNIT_RAM_D1)) ||
5286 	  (du && regs[2] && (regs[2]->unit == UNIT_RAM_D0)) ||
5287 	  (!du && regs[2] && (regs[2]->unit == UNIT_RAM_D1))) {
5288 	as_bad (_("DSP RAM pointer in incorrect unit"));
5289 	return NULL;
5290       }
5291 
5292       /* Is this a template definition?  */
5293       if (IS_TEMPLATE_DEF (insn))
5294 	{
5295 	  l = interpret_template_regs(l, insn, regs, regs_shift, &load,
5296 				      &dspram, size, &ls_shift, &au_shift,
5297 				      &au, &imm, &imm_shift, &imm_mask);
5298 
5299 	  if (l == NULL)
5300 	    return NULL;
5301 
5302 	  if (!dspram)
5303 	    mx_shift = 0;
5304 	}
5305 
5306       goto matched;
5307     }
5308 
5309   /* Group 2.  */
5310   if (template->arg_type & DSP_ARGS_2)
5311     {
5312       bool is_xsd = (MAJOR_OPCODE (template->meta_opcode) == OPC_MISC
5313 		     && MINOR_OPCODE (template->meta_opcode) == 0xa);
5314       bool is_fpu_mov = template->insn_type == INSN_DSP_FPU;
5315       bool to_fpu = ((template->meta_opcode >> 7) & 0x1) != 0;
5316 
5317       if (is_xsd)
5318 	du_shift = 0;
5319       else
5320 	du_shift = 24;
5321 
5322       l1_shift = 4;
5323 
5324       /* CMPs and TSTs don't store to their destination operand.  */
5325       ll = __parse_gp_reg (l, regs, is_cmp);
5326       if (ll == NULL)
5327 	{
5328 	  /* DSPe.r,Dx.r or DSPx.r,#I16 */
5329 	  if (template->arg_type & DSP_ARGS_DSP_SRC1)
5330 	    {
5331 	      l = parse_dsp_reg (l, regs, false, false);
5332 	      if (l == NULL)
5333 		{
5334 		  as_bad (_("invalid register operand #1"));
5335 		  return NULL;
5336 		}
5337 
5338 	      /* Only MOV instructions have a DSP register as a
5339 		 destination. Set the MOV DSPe.r opcode. The simple
5340 		 OR'ing is OK because the usual MOV opcode is 0x00.  */
5341 	      insn->bits = 0x91u << 24;
5342 	      du_shift = 0;
5343 	      l1_shift = 2;
5344 	      regs_shift[0] = 19;
5345 	    }
5346 	  else
5347 	    {
5348 	      as_bad (_("invalid register operand #2"));
5349 	      return NULL;
5350 	    }
5351 	}
5352       else
5353 	{
5354 	  l = ll;
5355 
5356 	  /* Everything but CMP and TST.  */
5357 	  if (MAJOR_OPCODE (template->meta_opcode) == OPC_ADD ||
5358 	      MAJOR_OPCODE (template->meta_opcode) == OPC_SUB ||
5359 	      MAJOR_OPCODE (insn->bits) == OPC_9 ||
5360 	      MAJOR_OPCODE (template->meta_opcode) == OPC_MISC ||
5361 	      ((template->meta_opcode & 0x0000002c) != 0))
5362 	    regs_shift[0] = 19;
5363 	  else
5364 	    regs_shift[0] = 14;
5365 	}
5366 
5367       if (!is_dsp_data_unit (regs[0]) && !(regs[0]->unit == UNIT_FX &&
5368 					   is_fpu_mov && to_fpu))
5369 	return NULL;
5370 
5371       du = (regs[0]->unit == UNIT_D1 || regs[0]->unit == UNIT_RAM_D1 ||
5372 	    regs[0]->unit == UNIT_ACC_D1);
5373 
5374       l = skip_comma (l);
5375 
5376       if (*l == IMM_CHAR)
5377 	{
5378 	  if (template->arg_type & DSP_ARGS_IMM &&
5379 	      !(is_mov && (MAJOR_OPCODE (insn->bits) != OPC_9)))
5380 	    {
5381 	      l = parse_imm16 (l, insn, &imm);
5382 	      if (l == NULL)
5383 		{
5384 		  as_bad (_("invalid immediate value"));
5385 		  return NULL;
5386 		}
5387 
5388 	      if (!within_signed_range (imm, IMM16_BITS))
5389 		return NULL;
5390 
5391 	      l1_shift = 2;
5392 	      regs_shift[0] = 19;
5393 
5394 	      imm_mask = 0xffff;
5395 	      imm_shift = 3;
5396 
5397 	      /* Set the I-bit unless it's a MOV because they're
5398 		 different.  */
5399 	      if (!(is_mov && MAJOR_OPCODE (insn->bits) == OPC_9))
5400 		insn->bits |= (1 << 25);
5401 
5402 	      /* All instructions that takes immediates also have bit 1 set.  */
5403 	      insn->bits |= (1 << 1);
5404 
5405 	      if (MAJOR_OPCODE (insn->bits) != OPC_9)
5406 		insn->bits |= (1 << 0);
5407 
5408 	      insn->bits &= ~(1 << 8);
5409 	    }
5410 	  else
5411 	    {
5412 	      as_bad (_("this instruction does not accept an immediate"));
5413 	      return NULL;
5414 	    }
5415 	}
5416       else
5417 	{
5418 	  if (MAJOR_OPCODE (insn->bits) != OPC_9)
5419 	    {
5420 	      insn->bits |= (1 << 8);
5421 	      l1_shift = 4;
5422 	    }
5423 
5424 	  ll = __parse_gp_reg (l, &regs[1], true);
5425 	  if (ll == NULL)
5426 	    {
5427 	      if (template->arg_type & DSP_ARGS_DSP_SRC2)
5428 		{
5429 		  l = parse_dsp_reg (l, &regs[1], false, false);
5430 		  if (l == NULL)
5431 		    {
5432 		      as_bad (_("invalid register operand #3"));
5433 		      return NULL;
5434 		    }
5435 
5436 		  /* MOV and NEG.  */
5437 		  if ((is_mov && (MAJOR_OPCODE (insn->bits) != OPC_9)) ||
5438 		      MAJOR_OPCODE (template->meta_opcode) == OPC_SUB)
5439 		    {
5440 		      if (is_accumulator_reg (regs[1]))
5441 			{
5442 			  if (is_fpu_mov)
5443 			    {
5444 			      as_bad (_("this instruction does not accept an accumulator"));
5445 			      return NULL;
5446 			    }
5447 			  ar_shift = 7;
5448 			  ar = 1;
5449 			  regs_shift[1] = 9;
5450 			}
5451 		      else
5452 			{
5453 			  du_shift = 0;
5454 			  l1_shift = 2;
5455 			  regs_shift[1] = 14;
5456 			  insn->bits = 0x92u << 24; /* Set opcode.  */
5457 			}
5458 		    }
5459 		}
5460 	      else
5461 		{
5462 		  as_bad (_("invalid register operand #4"));
5463 		  return NULL;
5464 		}
5465 	    }
5466 	  else
5467 	    {
5468 	      /* Set the o2r bit if required.  */
5469 	      if (!is_fpu_mov && units_need_o2r (regs[0]->unit, regs[1]->unit))
5470 		{
5471 		  o2r_reg = *regs[1];
5472 		  o2r_reg.no = lookup_o2r (0, du, regs[1]);
5473 		  regs[1] = &o2r_reg;
5474 		  o2r_shift = 0;
5475 		  o2r = 1;
5476 		}
5477 	      else if (!is_dsp_data_unit (regs[1]) &&
5478 		       !(is_fpu_mov && !to_fpu && regs[1]->unit == UNIT_FX))
5479 		return NULL;
5480 
5481 	      if (is_fpu_mov && to_fpu)
5482 		du = (regs[1]->unit == UNIT_D1 ||
5483 		      regs[1]->unit == UNIT_RAM_D1 ||
5484 		      regs[1]->unit == UNIT_ACC_D1);
5485 
5486 	      l = ll;
5487 
5488 	      if (MAJOR_OPCODE (insn->bits) == OPC_ADD ||
5489 		  MAJOR_OPCODE (template->meta_opcode) == OPC_SUB ||
5490 		  (((template->meta_opcode & 0x0000002c) == 0) &&
5491 		   MAJOR_OPCODE (template->meta_opcode) != OPC_MISC))
5492 		regs_shift[1] = 9;
5493 	      else
5494 		regs_shift[1] = 14;
5495 	    }
5496 	}
5497 
5498       /* If it's an 0x0 MOV or NEG set some lower bits.  */
5499       if ((MAJOR_OPCODE (insn->bits) == OPC_ADD ||
5500 	   MAJOR_OPCODE (template->meta_opcode) == OPC_SUB) && !is_fpu_mov)
5501 	{
5502 	  om_shift = 3;
5503 	  sc_shift = 5;
5504 	  insn->bits |= (1 << 2);
5505 	}
5506 
5507       /* Check for template definitions.  */
5508       if (IS_TEMPLATE_DEF (insn))
5509 	{
5510 	  l = interpret_template_regs(l, insn, regs, regs_shift, &load,
5511 				      &dspram, size, &ls_shift, &au_shift,
5512 				      &au, &imm, &imm_shift, &imm_mask);
5513 	  mx_shift = 0;
5514 
5515 	  if (l == NULL)
5516 	    return NULL;
5517 	}
5518       goto matched;
5519     }
5520 
5521   /* Group 3.  */
5522   du_shift = 24;
5523   l1_shift = 4;
5524 
5525   l = __parse_gp_reg (l, regs, false);
5526   if (l == NULL)
5527     {
5528       as_bad (_("invalid register operand"));
5529       return NULL;
5530     }
5531 
5532   l = skip_comma (l);
5533 
5534   if (*l == 'A')
5535     {
5536       l = parse_dsp_reg (l, &regs[1], false, false);
5537       if (l == NULL)
5538 	{
5539 	  as_bad (_("invalid accumulator register"));
5540 	  return NULL;
5541 	}
5542       ac = 1;
5543       ac_shift = 0;
5544     }
5545   else
5546     {
5547       l = __parse_gp_reg (l, &regs[1], true);
5548       if (l == NULL)
5549 	{
5550 	  as_bad (_("invalid register operand"));
5551 	  return NULL;
5552 	}
5553     }
5554 
5555   regs_shift[0] = 19;
5556   regs_shift[1] = 14;
5557 
5558   du = (regs[1]->unit == UNIT_D1 || regs[1]->unit == UNIT_ACC_D1
5559 	|| regs[1]->unit == UNIT_RAM_D1);
5560 
5561   l = skip_comma (l);
5562 
5563   if (*l == IMM_CHAR)
5564     {
5565       l = parse_imm_constant (l, insn, &imm);
5566       if (l == NULL)
5567 	{
5568 	  as_bad (_("invalid immediate value"));
5569 	  return NULL;
5570 	}
5571 
5572       if (!within_unsigned_range (imm, IMM5_BITS))
5573 	return NULL;
5574 
5575       imm_mask = 0x1f;
5576       imm_shift = 9;
5577 
5578       /* Set the I-bit */
5579       insn->bits |= (1 << 25);
5580     }
5581   else
5582     {
5583       regs_shift[2] = 9;
5584       l = __parse_gp_reg (l, &regs[2], true);
5585       if (l == NULL)
5586 	return NULL;
5587     }
5588 
5589   /* Check for post-processing R,G,B flags. Conditional instructions
5590      do not have these bits.  */
5591   if (insn->dsp_action_flags & DSP_ACTION_CLAMP9)
5592     {
5593       if ((template->meta_opcode >> 26) & 0x1)
5594 	{
5595 	  as_bad (_("conditional instruction cannot use G flag"));
5596 	  return NULL;
5597 	}
5598 
5599       insn->bits |= (1 << 3);
5600     }
5601 
5602   if (insn->dsp_action_flags & DSP_ACTION_CLAMP8)
5603     {
5604       if ((template->meta_opcode >> 26) & 0x1)
5605 	{
5606 	  as_bad (_("conditional instruction cannot use B flag"));
5607 	  return NULL;
5608 	}
5609 
5610       insn->bits |= (0x3 << 2);
5611     }
5612 
5613   if (insn->dsp_action_flags & DSP_ACTION_ROUND)
5614     {
5615       if ((template->meta_opcode >> 26) & 0x1)
5616 	{
5617 	  as_bad (_("conditional instruction cannot use R flag"));
5618 	  return NULL;
5619 	}
5620       insn->bits |= (1 << 2);
5621     }
5622 
5623   /* Conditional Data Unit Shift instructions cannot be dual unit.  */
5624   if ((template->meta_opcode >> 26) & 0x1)
5625     ls_shift = INVALID_SHIFT;
5626 
5627   /* The Condition Is Always (CA) bit must be set if we're targeting a
5628      Ux.r register as the destination. This means that we can't have
5629      any other condition bits set.  */
5630   if (!is_same_data_unit (regs[1]->unit, regs[0]->unit))
5631     {
5632       /* Set both the Conditional bit and the Condition is Always bit.  */
5633       insn->bits |= (1 << 26);
5634       insn->bits |= (1 << 5);
5635 
5636       /* Fill out the Ud field.  */
5637       insn->bits |= (regs[0]->unit << 1);
5638     }
5639 
5640   if (IS_TEMPLATE_DEF (insn))
5641     {
5642       l = interpret_template_regs(l, insn, regs, regs_shift, &load,
5643 				  &dspram, size, &ls_shift, &au_shift,
5644 				  &au, &imm, &imm_shift, &imm_mask);
5645 
5646       if (l == NULL)
5647 	return NULL;
5648 
5649       if (!dspram)
5650 	mx_shift = 5;
5651     }
5652 
5653   /* Fall through.  */
5654  matched:
5655 
5656   /* Set the registers and immediate values.  */
5657   if (regs_shift[0] != INVALID_SHIFT)
5658     insn->bits |= (regs[0]->no << regs_shift[0]);
5659 
5660   if (regs_shift[1] != INVALID_SHIFT)
5661     insn->bits |= (regs[1]->no << regs_shift[1]);
5662 
5663   if (regs_shift[2] != INVALID_SHIFT)
5664     insn->bits |= (regs[2]->no << regs_shift[2]);
5665 
5666   /* Does this insn have an 'IMM' bit? The immediate value should
5667      already have been masked.  */
5668   if (imm_shift != INVALID_SHIFT)
5669     insn->bits |= ((imm & imm_mask) << imm_shift);
5670 
5671   /* Does this insn have an 'AU' bit? */
5672   if (au_shift != INVALID_SHIFT)
5673     insn->bits |= (au << au_shift);
5674 
5675   /* Does this instruction have an 'LS' bit?  */
5676   if (ls_shift != INVALID_SHIFT)
5677     insn->bits |= (load << ls_shift);
5678 
5679   /* Does this instruction have an 'AR' bit?  */
5680   if (ar)
5681       insn->bits |= (1 << ar_shift);
5682 
5683   if (du_shift != INVALID_SHIFT)
5684     insn->bits |= (du << du_shift);
5685 
5686   if (sc_shift != INVALID_SHIFT)
5687     insn->bits |= (sc << sc_shift);
5688 
5689   if (om_shift != INVALID_SHIFT)
5690     insn->bits |= (om << om_shift);
5691 
5692   if (o2r_shift != INVALID_SHIFT)
5693     insn->bits |= (o2r << o2r_shift);
5694 
5695   if (qn_shift != INVALID_SHIFT)
5696     insn->bits |= (qn << qn_shift);
5697 
5698   if (qr_shift != INVALID_SHIFT)
5699     insn->bits |= (qr << qr_shift);
5700 
5701   if (qd_shift != INVALID_SHIFT)
5702     insn->bits |= (is_quickrot64 << qd_shift);
5703 
5704   if (a1_shift != INVALID_SHIFT)
5705     insn->bits |= (a1 << a1_shift);
5706 
5707   if (a2_shift != INVALID_SHIFT)
5708     insn->bits |= (a2 << a2_shift);
5709 
5710   if (su_shift != INVALID_SHIFT)
5711     insn->bits |= (su << su_shift);
5712 
5713   if (imm_shift != INVALID_SHIFT)
5714     insn->bits |= ((imm & imm_mask) << imm_shift);
5715 
5716   if (ac_shift != INVALID_SHIFT)
5717     insn->bits |= (ac << ac_shift);
5718 
5719   if (mx_shift != INVALID_SHIFT)
5720     insn->bits |= (mx << mx_shift);
5721 
5722   if (is_dual)
5723     {
5724       if (l1_shift == INVALID_SHIFT)
5725 	{
5726 	  as_bad (_("'L' modifier not valid for this instruction"));
5727 	  return NULL;
5728 	}
5729 
5730       insn->bits |= (1 << l1_shift);
5731     }
5732 
5733   insn->len = 4;
5734 
5735   return l;
5736 }
5737 
5738 typedef const char *(*insn_parser)(const char *, metag_insn *,
5739 				   const insn_template *);
5740 
5741 /* Parser table.  */
5742 static const insn_parser insn_parsers[ENC_MAX] =
5743   {
5744     [ENC_NONE] = parse_none,
5745     [ENC_MOV_U2U] = parse_mov_u2u,
5746     [ENC_MOV_PORT] = parse_mov_port,
5747     [ENC_MMOV] = parse_mmov,
5748     [ENC_MDRD] = parse_mdrd,
5749     [ENC_MOVL_TTREC] = parse_movl_ttrec,
5750     [ENC_GET_SET] = parse_get_set,
5751     [ENC_GET_SET_EXT] = parse_get_set_ext,
5752     [ENC_MGET_MSET] = parse_mget_mset,
5753     [ENC_COND_SET] = parse_cond_set,
5754     [ENC_XFR] = parse_xfr,
5755     [ENC_MOV_CT] = parse_mov_ct,
5756     [ENC_SWAP] = parse_swap,
5757     [ENC_JUMP] = parse_jump,
5758     [ENC_CALLR] = parse_callr,
5759     [ENC_ALU] = parse_alu,
5760     [ENC_SHIFT] = parse_shift,
5761     [ENC_MIN_MAX] = parse_min_max,
5762     [ENC_BITOP] = parse_bitop,
5763     [ENC_CMP] = parse_cmp,
5764     [ENC_BRANCH] = parse_branch,
5765     [ENC_KICK] = parse_kick,
5766     [ENC_SWITCH] = parse_switch,
5767     [ENC_CACHER] = parse_cacher,
5768     [ENC_CACHEW] = parse_cachew,
5769     [ENC_ICACHE] = parse_icache,
5770     [ENC_LNKGET] = parse_lnkget,
5771     [ENC_FMOV] = parse_fmov,
5772     [ENC_FMMOV] = parse_fmmov,
5773     [ENC_FMOV_DATA] = parse_fmov_data,
5774     [ENC_FMOV_I] = parse_fmov_i,
5775     [ENC_FPACK] = parse_fpack,
5776     [ENC_FSWAP] = parse_fswap,
5777     [ENC_FCMP] = parse_fcmp,
5778     [ENC_FMINMAX] = parse_fminmax,
5779     [ENC_FCONV] = parse_fconv,
5780     [ENC_FCONVX] = parse_fconvx,
5781     [ENC_FBARITH] = parse_fbarith,
5782     [ENC_FEARITH] = parse_fearith,
5783     [ENC_FREC] = parse_frec,
5784     [ENC_FSIMD] = parse_fsimd,
5785     [ENC_FGET_SET_ACF] = parse_fget_set_acf,
5786     [ENC_DGET_SET] = parse_dget_set,
5787     [ENC_DTEMPLATE] = parse_dtemplate,
5788     [ENC_DALU] = parse_dalu,
5789   };
5790 
5791 struct metag_core_option
5792 {
5793   const char *name;
5794   unsigned int value;
5795 };
5796 
5797 /* CPU type options.  */
5798 static const struct metag_core_option metag_cpus[] =
5799   {
5800     {"all",               CoreMeta11|CoreMeta12|CoreMeta21},
5801     {"metac11",           CoreMeta11},
5802     {"metac12",           CoreMeta12},
5803     {"metac21",           CoreMeta21},
5804     {NULL,                0},
5805   };
5806 
5807 /* FPU type options.  */
5808 static const struct metag_core_option metag_fpus[] =
5809   {
5810     {"metac21",           FpuMeta21},
5811     {NULL,                0},
5812   };
5813 
5814 /* DSP type options.  */
5815 static const struct metag_core_option metag_dsps[] =
5816   {
5817     {"metac21",           DspMeta21},
5818     {NULL,                0},
5819   };
5820 
5821 /* Parse a CPU command line option.  */
5822 static bool
metag_parse_cpu(const char * str)5823 metag_parse_cpu (const char * str)
5824 {
5825   const struct metag_core_option * opt;
5826   int optlen;
5827 
5828   optlen = strlen (str);
5829 
5830   if (optlen == 0)
5831     {
5832       as_bad (_("missing cpu name `%s'"), str);
5833       return 0;
5834     }
5835 
5836   for (opt = metag_cpus; opt->name != NULL; opt++)
5837     if (strncmp (opt->name, str, optlen) == 0)
5838       {
5839 	mcpu_opt = opt->value;
5840 	return 1;
5841       }
5842 
5843   as_bad (_("unknown cpu `%s'"), str);
5844   return 0;
5845 }
5846 
5847 /* Parse an FPU command line option.  */
5848 static bool
metag_parse_fpu(const char * str)5849 metag_parse_fpu (const char * str)
5850 {
5851   const struct metag_core_option * opt;
5852   int optlen;
5853 
5854   optlen = strlen (str);
5855 
5856   if (optlen == 0)
5857     {
5858       as_bad (_("missing fpu name `%s'"), str);
5859       return 0;
5860     }
5861 
5862   for (opt = metag_fpus; opt->name != NULL; opt++)
5863     if (strncmp (opt->name, str, optlen) == 0)
5864       {
5865 	mfpu_opt = opt->value;
5866 	return 1;
5867       }
5868 
5869   as_bad (_("unknown fpu `%s'"), str);
5870   return 0;
5871 }
5872 
5873 /* Parse a DSP command line option.  */
5874 static bool
metag_parse_dsp(const char * str)5875 metag_parse_dsp (const char * str)
5876 {
5877   const struct metag_core_option * opt;
5878   int optlen;
5879 
5880   optlen = strlen (str);
5881 
5882   if (optlen == 0)
5883     {
5884       as_bad (_("missing DSP name `%s'"), str);
5885       return 0;
5886     }
5887 
5888   for (opt = metag_dsps; opt->name != NULL; opt++)
5889     if (strncmp (opt->name, str, optlen) == 0)
5890       {
5891 	mdsp_opt = opt->value;
5892 	return 1;
5893       }
5894 
5895   as_bad (_("unknown DSP `%s'"), str);
5896   return 0;
5897 }
5898 
5899 struct metag_long_option
5900 {
5901   const char *option;			/* Substring to match.  */
5902   const char *help;			/* Help information.  */
5903   bool (*func) (const char *subopt);	/* Function to decode sub-option.  */
5904   const char *deprecated;		/* If non-null, print this message.  */
5905 };
5906 
5907 struct metag_long_option metag_long_opts[] =
5908   {
5909     {"mcpu=", N_("<cpu name>\t  assemble for CPU <cpu name>"),
5910      metag_parse_cpu, NULL},
5911     {"mfpu=", N_("<fpu name>\t  assemble for FPU architecture <fpu name>"),
5912      metag_parse_fpu, NULL},
5913     {"mdsp=", N_("<dsp name>\t  assemble for DSP architecture <dsp name>"),
5914      metag_parse_dsp, NULL},
5915     {NULL, NULL, 0, NULL}
5916   };
5917 
5918 int
md_parse_option(int c,const char * arg)5919 md_parse_option (int c, const char * arg)
5920 {
5921   struct metag_long_option *lopt;
5922 
5923   for (lopt = metag_long_opts; lopt->option != NULL; lopt++)
5924     {
5925       /* These options are expected to have an argument.  */
5926       if (c == lopt->option[0]
5927 	  && arg != NULL
5928 	  && startswith (arg, lopt->option + 1))
5929 	{
5930 #if WARN_DEPRECATED
5931 	      /* If the option is deprecated, tell the user.  */
5932 	      if (lopt->deprecated != NULL)
5933 		as_tsktsk (_("option `-%c%s' is deprecated: %s"), c, arg,
5934 			   _(lopt->deprecated));
5935 #endif
5936 
5937 	      /* Call the sup-option parser.  */
5938 	      return lopt->func (arg + strlen (lopt->option) - 1);
5939 	}
5940     }
5941 
5942   return 0;
5943 }
5944 
5945 void
md_show_usage(FILE * stream)5946 md_show_usage (FILE * stream)
5947 {
5948   struct metag_long_option *lopt;
5949 
5950   fprintf (stream, _(" Meta specific command line options:\n"));
5951 
5952   for (lopt = metag_long_opts; lopt->option != NULL; lopt++)
5953     if (lopt->help != NULL)
5954       fprintf (stream, "  -%s%s\n", lopt->option, _(lopt->help));
5955 }
5956 
5957 /* The target specific pseudo-ops which we support.  */
5958 const pseudo_typeS md_pseudo_table[] =
5959 {
5960   { "word",	cons,		2 },
5961   { NULL, 	NULL, 		0 }
5962 };
5963 
5964 void
md_begin(void)5965 md_begin (void)
5966 {
5967   int c;
5968 
5969   for (c = 0; c < 256; c++)
5970     {
5971       if (ISDIGIT (c))
5972 	{
5973 	  register_chars[c] = c;
5974 	  /* LOCK0, LOCK1, LOCK2.  */
5975 	  mnemonic_chars[c] = c;
5976 	}
5977       else if (ISLOWER (c))
5978 	{
5979 	  register_chars[c] = c;
5980 	  mnemonic_chars[c] = c;
5981 	}
5982       else if (ISUPPER (c))
5983 	{
5984 	  register_chars[c] = c;
5985 	  mnemonic_chars[c] = c;
5986 	}
5987       else if (c == '.')
5988 	{
5989 	  register_chars[c] = c;
5990 	}
5991     }
5992 }
5993 
5994 /* Parse a split condition code prefix.  */
5995 static const char *
parse_split_condition(const char * line,metag_insn * insn)5996 parse_split_condition (const char *line, metag_insn *insn)
5997 {
5998   const char *l = line;
5999   const split_condition *scond;
6000   split_condition entry;
6001   char buf[4];
6002 
6003   memcpy (buf, l, 4);
6004   buf[3] = '\0';
6005 
6006   entry.name = buf;
6007 
6008   scond = (const split_condition *) htab_find (scond_htab, &entry);
6009 
6010   if (!scond)
6011     return NULL;
6012 
6013   insn->scond = scond->code;
6014 
6015   return l + strlen (scond->name);
6016 }
6017 
6018 /* Parse an instruction prefix - F for float, D for DSP - and associated
6019    flags and condition codes.  */
6020 static const char *
parse_prefix(const char * line,metag_insn * insn)6021 parse_prefix (const char *line, metag_insn *insn)
6022 {
6023   const char *l = line;
6024 
6025   l = skip_whitespace (l);
6026 
6027   insn->type = INSN_GP;
6028 
6029   if (TOLOWER (*l) == FPU_PREFIX_CHAR)
6030     {
6031       if (strncasecmp (l, FFB_INSN, strlen(FFB_INSN)))
6032 	{
6033 	  insn->type = INSN_FPU;
6034 
6035 	  l++;
6036 
6037 	  if (*l == END_OF_INSN)
6038 	    {
6039 	      as_bad (_("premature end of floating point prefix"));
6040 	      return NULL;
6041 	    }
6042 
6043 	  if (TOLOWER (*l) == FPU_DOUBLE_CHAR)
6044 	    {
6045 	      insn->fpu_width = FPU_WIDTH_DOUBLE;
6046 	      l++;
6047 	    }
6048 	  else if (TOLOWER (*l) == FPU_PAIR_CHAR)
6049 	    {
6050 	      const char *l2 = l;
6051 
6052 	      /* Check this isn't a split condition beginning with L.  */
6053 	      l2 = parse_split_condition (l2, insn);
6054 
6055 	      if (l2 && is_whitespace_char (*l2))
6056 		{
6057 		  l = l2;
6058 		}
6059 	      else
6060 		{
6061 		  insn->fpu_width = FPU_WIDTH_PAIR;
6062 		  l++;
6063 		}
6064 	    }
6065 	  else
6066 	    {
6067 	      insn->fpu_width = FPU_WIDTH_SINGLE;
6068 	    }
6069 
6070 	  if (TOLOWER (*l) == FPU_ACTION_ABS_CHAR)
6071 	    {
6072 	      insn->fpu_action_flags |= FPU_ACTION_ABS;
6073 	      l++;
6074 	    }
6075 	  else if (TOLOWER (*l) == FPU_ACTION_INV_CHAR)
6076 	    {
6077 	      insn->fpu_action_flags |= FPU_ACTION_INV;
6078 	      l++;
6079 	    }
6080 
6081 	  if (TOLOWER (*l) == FPU_ACTION_QUIET_CHAR)
6082 	    {
6083 	      insn->fpu_action_flags |= FPU_ACTION_QUIET;
6084 	      l++;
6085 	    }
6086 
6087 	  if (TOLOWER (*l) == FPU_ACTION_ZERO_CHAR)
6088 	    {
6089 	      insn->fpu_action_flags |= FPU_ACTION_ZERO;
6090 	      l++;
6091 	    }
6092 
6093 	  if (! is_whitespace_char (*l))
6094 	    {
6095 	      l = parse_split_condition (l, insn);
6096 
6097 	      if (!l)
6098 		{
6099 		  as_bad (_("unknown floating point prefix character"));
6100 		  return NULL;
6101 		}
6102 	    }
6103 
6104 	  l = skip_space (l);
6105 	}
6106     }
6107   else if (TOLOWER (*l) == DSP_PREFIX_CHAR)
6108     {
6109       if (strncasecmp (l, DCACHE_INSN, strlen (DCACHE_INSN)) &&
6110 	  strncasecmp (l, DEFR_INSN, strlen (DEFR_INSN)))
6111 	{
6112 	  const char *ll = l;
6113 	  insn->type = INSN_DSP;
6114 
6115 	  l++;
6116 
6117 	  insn->dsp_width = DSP_WIDTH_SINGLE;
6118 
6119 	  while (!is_whitespace_char (*l))
6120 	    {
6121 	      /* We have to check for split condition codes first
6122 		 because they are the longest strings to match,
6123 		 e.g. if the string contains "LLS" we want it to match
6124 		 the split condition code "LLS", not the dual unit
6125 		 character "L".  */
6126 	      ll = l;
6127 	      l = parse_split_condition (l, insn);
6128 
6129 	      if (l == NULL)
6130 		l = ll;
6131 	      else
6132 		continue;
6133 
6134 	      /* Accept an FPU prefix char which may be used when doing
6135 		 template MOV with FPU registers. */
6136 	      if (TOLOWER(*l) == FPU_PREFIX_CHAR)
6137 		{
6138 		  insn->type = INSN_DSP_FPU;
6139 		  l++;
6140 		  continue;
6141 		}
6142 
6143 	      if (TOLOWER(*l) == DSP_DUAL_CHAR)
6144 		{
6145 		  insn->dsp_width = DSP_WIDTH_DUAL;
6146 		  l++;
6147 		  continue;
6148 		}
6149 
6150 	      if (TOLOWER(*l) == DSP_ACTION_QR64_CHAR)
6151 		{
6152 		  insn->dsp_action_flags |= DSP_ACTION_QR64;
6153 		  l++;
6154 		  continue;
6155 		}
6156 
6157 	      if (TOLOWER(*l) == DSP_ACTION_UMUL_CHAR)
6158 		{
6159 		  insn->dsp_action_flags |= DSP_ACTION_UMUL;
6160 		  l++;
6161 		  continue;
6162 		}
6163 
6164 	      if (TOLOWER(*l) == DSP_ACTION_ROUND_CHAR)
6165 		{
6166 		  insn->dsp_action_flags |= DSP_ACTION_ROUND;
6167 		  l++;
6168 		  continue;
6169 		}
6170 
6171 	      if (TOLOWER(*l) == DSP_ACTION_CLAMP9_CHAR)
6172 		{
6173 		  insn->dsp_action_flags |= DSP_ACTION_CLAMP9;
6174 		  l++;
6175 		  continue;
6176 		}
6177 
6178 	      if (TOLOWER(*l) == DSP_ACTION_CLAMP8_CHAR)
6179 		{
6180 		  insn->dsp_action_flags |= DSP_ACTION_CLAMP8;
6181 		  l++;
6182 		  continue;
6183 		}
6184 
6185 	      if (TOLOWER(*l) == DSP_ACTION_MOD_CHAR)
6186 		{
6187 		  insn->dsp_action_flags |= DSP_ACTION_MOD;
6188 		  l++;
6189 		  continue;
6190 		}
6191 
6192 	      if (TOLOWER(*l) == DSP_ACTION_ACC_ZERO_CHAR)
6193 		{
6194 		  insn->dsp_action_flags |= DSP_ACTION_ACC_ZERO;
6195 		  l++;
6196 		  continue;
6197 		}
6198 
6199 	      if (TOLOWER(*l) == DSP_ACTION_ACC_ADD_CHAR)
6200 		{
6201 		  insn->dsp_action_flags |= DSP_ACTION_ACC_ADD;
6202 		  l++;
6203 		  continue;
6204 		}
6205 
6206 	      if (TOLOWER(*l) == DSP_ACTION_ACC_SUB_CHAR)
6207 		{
6208 		  insn->dsp_action_flags |= DSP_ACTION_ACC_SUB;
6209 		  l++;
6210 		  continue;
6211 		}
6212 
6213 	      if (TOLOWER(*l) == DSP_ACTION_OV_CHAR)
6214 		{
6215 		  insn->dsp_action_flags |= DSP_ACTION_OV;
6216 		  l++;
6217 		  continue;
6218 		}
6219 
6220 	      if (TOLOWER(*l) == DSP_DAOPPAME_8_CHAR)
6221 		{
6222 		  insn->dsp_daoppame_flags |= DSP_DAOPPAME_8;
6223 		  l++;
6224 		  continue;
6225 		}
6226 
6227 	      if (TOLOWER(*l) == DSP_DAOPPAME_16_CHAR)
6228 		{
6229 		  insn->dsp_daoppame_flags |= DSP_DAOPPAME_16;
6230 		  l++;
6231 		  continue;
6232 		}
6233 
6234 	      if (TOLOWER(*l) == DSP_DAOPPAME_TEMP_CHAR)
6235 		{
6236 		  insn->dsp_daoppame_flags |= DSP_DAOPPAME_TEMP;
6237 		  l++;
6238 		  continue;
6239 		}
6240 
6241 	      if (TOLOWER(*l) == DSP_DAOPPAME_HIGH_CHAR)
6242 		{
6243 		  insn->dsp_daoppame_flags |= DSP_DAOPPAME_HIGH;
6244 		  l++;
6245 		  continue;
6246 		}
6247 
6248 	      as_bad (_("unknown DSP prefix character %c %s"), *l, l);
6249 	      return NULL;
6250 	    }
6251 
6252 	  l = skip_space (l);
6253 	}
6254     }
6255 
6256   return l;
6257 }
6258 
6259 /* Return a list of appropriate instruction parsers for MNEMONIC.  */
6260 static insn_templates *
find_insn_templates(const char * mnemonic)6261 find_insn_templates (const char *mnemonic)
6262 {
6263   insn_template template;
6264   insn_templates entry;
6265   insn_templates *slot;
6266 
6267   entry.template = &template;
6268 
6269   memcpy ((void *)&entry.template->name, &mnemonic, sizeof (char *));
6270 
6271   slot = (insn_templates *) htab_find (mnemonic_htab, &entry);
6272 
6273   if (slot)
6274     return slot;
6275 
6276   return NULL;
6277 }
6278 
6279 /* Make an uppercase copy of SRC into DST and return DST.  */
6280 static char *
strupper(char * dst,const char * src)6281 strupper (char * dst, const char *src)
6282 {
6283   size_t i = 0;
6284 
6285   while (src[i])
6286     {
6287       dst[i] = TOUPPER (src[i]);
6288       i++;
6289     }
6290 
6291   dst[i] = 0;
6292 
6293   return dst;
6294 }
6295 
6296 /* Calculate a hash value for a template. */
6297 static hashval_t
hash_templates(const void * p)6298 hash_templates (const void *p)
6299 {
6300   insn_templates *tp = (insn_templates *)p;
6301   char buf[MAX_MNEMONIC_LEN];
6302 
6303   strupper (buf, tp->template->name);
6304 
6305   return htab_hash_string (buf);
6306 }
6307 
6308 /* Check if two templates are equal.  */
6309 static int
eq_templates(const void * a,const void * b)6310 eq_templates (const void *a, const void *b)
6311 {
6312   insn_templates *ta = (insn_templates *)a;
6313   insn_templates *tb = (insn_templates *)b;
6314   return strcasecmp (ta->template->name, tb->template->name) == 0;
6315 }
6316 
6317 /* Create the hash table required for parsing instructions.  */
6318 static void
create_mnemonic_htab(void)6319 create_mnemonic_htab (void)
6320 {
6321   size_t i, num_templates = sizeof(metag_optab)/sizeof(metag_optab[0]);
6322 
6323   mnemonic_htab = htab_create_alloc (num_templates, hash_templates,
6324 				     eq_templates, NULL, xcalloc, free);
6325 
6326   for (i = 0; i < num_templates; i++)
6327     {
6328       const insn_template *template = &metag_optab[i];
6329       insn_templates **slot = NULL;
6330       insn_templates *new_entry;
6331 
6332       new_entry = XNEW (insn_templates);
6333 
6334       new_entry->template = template;
6335       new_entry->next = NULL;
6336 
6337       slot = (insn_templates **) htab_find_slot (mnemonic_htab, new_entry,
6338 						 INSERT);
6339 
6340       if (*slot)
6341 	{
6342 	  insn_templates *last_entry = *slot;
6343 
6344 	  while (last_entry->next)
6345 	    last_entry = last_entry->next;
6346 
6347 	  last_entry->next = new_entry;
6348 	}
6349       else
6350 	{
6351 	  *slot = new_entry;
6352 	}
6353     }
6354 }
6355 
6356 /* Calculate a hash value for a register. */
6357 static hashval_t
hash_regs(const void * p)6358 hash_regs (const void *p)
6359 {
6360   metag_reg *rp = (metag_reg *)p;
6361   char buf[MAX_REG_LEN];
6362 
6363   strupper (buf, rp->name);
6364 
6365   return htab_hash_string (buf);
6366 }
6367 
6368 /* Check if two registers are equal.  */
6369 static int
eq_regs(const void * a,const void * b)6370 eq_regs (const void *a, const void *b)
6371 {
6372   metag_reg *ra = (metag_reg *)a;
6373   metag_reg *rb = (metag_reg *)b;
6374   return strcasecmp (ra->name, rb->name) == 0;
6375 }
6376 
6377 /* Create the hash table required for parsing registers.  */
6378 static void
create_reg_htab(void)6379 create_reg_htab (void)
6380 {
6381   size_t i, num_regs = sizeof(metag_regtab)/sizeof(metag_regtab[0]);
6382 
6383   reg_htab = htab_create_alloc (num_regs, hash_regs,
6384 				eq_regs, NULL, xcalloc, free);
6385 
6386   for (i = 0; i < num_regs; i++)
6387     {
6388       const metag_reg *reg = &metag_regtab[i];
6389       const metag_reg **slot;
6390 
6391       slot = (const metag_reg **) htab_find_slot (reg_htab, reg, INSERT);
6392 
6393       if (!*slot)
6394 	*slot = reg;
6395     }
6396 }
6397 
6398 /* Create the hash table required for parsing DSP registers.  */
6399 static void
create_dspreg_htabs(void)6400 create_dspreg_htabs (void)
6401 {
6402   size_t i, num_regs = sizeof(metag_dsp_regtab)/sizeof(metag_dsp_regtab[0]);
6403   size_t h;
6404 
6405   dsp_reg_htab = htab_create_alloc (num_regs, hash_regs,
6406 				    eq_regs, NULL, xcalloc, free);
6407 
6408   for (i = 0; i < num_regs; i++)
6409     {
6410       const metag_reg *reg = &metag_dsp_regtab[i];
6411       const metag_reg **slot;
6412 
6413       slot = (const metag_reg **) htab_find_slot (dsp_reg_htab, reg, INSERT);
6414 
6415       /* Make sure there are no hash table collisions, which would
6416 	 require chaining entries.  */
6417       gas_assert (*slot == NULL);
6418       *slot = reg;
6419     }
6420 
6421   num_regs = sizeof(metag_dsp_tmpl_regtab[0])/sizeof(metag_dsp_tmpl_regtab[0][0]);
6422 
6423   for (h = 0; h < 2; h++)
6424     {
6425       dsp_tmpl_reg_htab[h] = htab_create_alloc (num_regs, hash_regs,
6426 						eq_regs, NULL, xcalloc, free);
6427     }
6428 
6429   for (h = 0; h < 2; h++)
6430     {
6431       for (i = 0; i < num_regs; i++)
6432 	{
6433 	  const metag_reg *reg = &metag_dsp_tmpl_regtab[h][i];
6434 	  const metag_reg **slot;
6435 	  slot = (const metag_reg **) htab_find_slot (dsp_tmpl_reg_htab[h],
6436 						      reg, INSERT);
6437 
6438 	  /* Make sure there are no hash table collisions, which would
6439 	     require chaining entries.  */
6440 	  gas_assert (*slot == NULL);
6441 	  *slot = reg;
6442 	}
6443     }
6444 }
6445 
6446 /* Calculate a hash value for a split condition code. */
6447 static hashval_t
hash_scond(const void * p)6448 hash_scond (const void *p)
6449 {
6450   split_condition *cp = (split_condition *)p;
6451   char buf[4];
6452 
6453   strupper (buf, cp->name);
6454 
6455   return htab_hash_string (buf);
6456 }
6457 
6458 /* Check if two split condition codes are equal.  */
6459 static int
eq_scond(const void * a,const void * b)6460 eq_scond (const void *a, const void *b)
6461 {
6462   split_condition *ra = (split_condition *)a;
6463   split_condition *rb = (split_condition *)b;
6464 
6465   return strcasecmp (ra->name, rb->name) == 0;
6466 }
6467 
6468 /* Create the hash table required for parsing split condition codes.  */
6469 static void
create_scond_htab(void)6470 create_scond_htab (void)
6471 {
6472   size_t i, nentries;
6473 
6474   nentries = sizeof (metag_scondtab) / sizeof (metag_scondtab[0]);
6475 
6476   scond_htab = htab_create_alloc (nentries, hash_scond, eq_scond,
6477 				  NULL, xcalloc, free);
6478   for (i = 0; i < nentries; i++)
6479     {
6480       const split_condition *scond = &metag_scondtab[i];
6481       const split_condition **slot;
6482 
6483       slot = (const split_condition **) htab_find_slot (scond_htab,
6484 							scond, INSERT);
6485       /* Make sure there are no hash table collisions, which would
6486 	 require chaining entries.  */
6487       gas_assert (*slot == NULL);
6488       *slot = scond;
6489     }
6490 }
6491 
6492 /* Entry point for instruction parsing.  */
6493 static bool
parse_insn(const char * line,metag_insn * insn)6494 parse_insn (const char *line, metag_insn *insn)
6495 {
6496   char mnemonic[MAX_MNEMONIC_LEN];
6497   const char *l = line;
6498   size_t mnemonic_len = 0;
6499   insn_templates *templates;
6500 
6501   l = skip_space (l);
6502 
6503   while (is_mnemonic_char(*l))
6504     {
6505       l++;
6506       mnemonic_len++;
6507     }
6508 
6509   if (mnemonic_len >= MAX_MNEMONIC_LEN)
6510     {
6511       as_bad (_("instruction mnemonic too long: %s"), line);
6512       return false;
6513     }
6514 
6515   strncpy(mnemonic, line, mnemonic_len);
6516 
6517   mnemonic[mnemonic_len] = '\0';
6518 
6519   templates = find_insn_templates (mnemonic);
6520 
6521   if (templates)
6522     {
6523       insn_templates *current_template = templates;
6524 
6525       l = skip_space (l);
6526 
6527       while (current_template)
6528 	{
6529 	  const insn_template *template = current_template->template;
6530 	  enum insn_encoding encoding = template->encoding;
6531 	  insn_parser parser = insn_parsers[encoding];
6532 
6533 	  current_template = current_template->next;
6534 
6535 	  if (template->insn_type == INSN_GP &&
6536 	      !(template->core_flags & mcpu_opt))
6537 	    continue;
6538 
6539 	  if (template->insn_type == INSN_FPU &&
6540 	      !(template->core_flags & mfpu_opt))
6541 	    continue;
6542 
6543 	  if (template->insn_type == INSN_DSP &&
6544 	      !(template->core_flags & mdsp_opt))
6545 	    continue;
6546 
6547 	  if (template->insn_type == INSN_DSP_FPU &&
6548 	      !((template->core_flags & mdsp_opt) &&
6549 		(template->core_flags & mfpu_opt)))
6550 	    continue;
6551 
6552 	  /* DSP instructions always require special decoding */
6553 	  if ((insn->type == INSN_DSP && (template->insn_type != INSN_DSP)) ||
6554 	      ((template->insn_type == INSN_DSP) && insn->type != INSN_DSP) ||
6555 	      (insn->type == INSN_DSP_FPU && (template->insn_type != INSN_DSP_FPU)) ||
6556 	      ((template->insn_type == INSN_DSP_FPU) && insn->type != INSN_DSP_FPU))
6557 	    continue;
6558 
6559 	  if (parser)
6560 	    {
6561 	      const char *end = parser(l, insn, template);
6562 
6563 	      if (end != NULL)
6564 		{
6565 		  if (*end != END_OF_INSN)
6566 		    as_bad (_("junk at end of line: \"%s\""), line);
6567 		  else
6568 		    return true;
6569 		}
6570 	    }
6571 	}
6572 
6573       as_bad (_("failed to assemble instruction: \"%s\""), line);
6574     }
6575   else
6576     {
6577       if (insn->type == INSN_FPU)
6578 	as_bad (_("unknown floating point mnemonic: \"%s\""), mnemonic);
6579       else
6580 	as_bad (_("unknown mnemonic: \"%s\""), mnemonic);
6581     }
6582   return false;
6583 }
6584 
6585 static void
output_insn(metag_insn * insn)6586 output_insn (metag_insn *insn)
6587 {
6588   char *output;
6589 
6590   output = frag_more (insn->len);
6591   dwarf2_emit_insn (insn->len);
6592 
6593   if (insn->reloc_type != BFD_RELOC_UNUSED)
6594     {
6595       fix_new_exp (frag_now, output - frag_now->fr_literal,
6596 		   insn->reloc_size, &insn->reloc_exp,
6597 		   insn->reloc_pcrel, insn->reloc_type);
6598     }
6599 
6600   md_number_to_chars (output, insn->bits, insn->len);
6601 }
6602 
6603 void
md_assemble(char * line)6604 md_assemble (char *line)
6605 {
6606   const char *l = line;
6607   metag_insn insn;
6608 
6609   memset (&insn, 0, sizeof(insn));
6610 
6611   insn.reloc_type = BFD_RELOC_UNUSED;
6612   insn.reloc_pcrel = 0;
6613   insn.reloc_size = 4;
6614 
6615   if (!mnemonic_htab)
6616     {
6617       create_mnemonic_htab ();
6618       create_reg_htab ();
6619       create_dspreg_htabs ();
6620       create_scond_htab ();
6621     }
6622 
6623   l = parse_prefix (l, &insn);
6624 
6625   if (l == NULL)
6626     return;
6627 
6628   if (insn.type == INSN_DSP &&
6629       !mdsp_opt)
6630     {
6631       as_bad (_("cannot assemble DSP instruction, DSP option not set: %s"),
6632 	      line);
6633       return;
6634     }
6635   else if (insn.type == INSN_FPU &&
6636 	   !mfpu_opt)
6637     {
6638       as_bad (_("cannot assemble FPU instruction, FPU option not set: %s"),
6639 	      line);
6640       return;
6641     }
6642 
6643   if (!parse_insn (l, &insn))
6644     return;
6645 
6646   output_insn (&insn);
6647 }
6648 
6649 void
md_operand(expressionS * expressionP)6650 md_operand (expressionS * expressionP)
6651 {
6652   if (* input_line_pointer == IMM_CHAR)
6653     {
6654       input_line_pointer ++;
6655       expression (expressionP);
6656     }
6657 }
6658 
6659 valueT
md_section_align(segT segment ATTRIBUTE_UNUSED,valueT size)6660 md_section_align (segT segment ATTRIBUTE_UNUSED, valueT size)
6661 {
6662   return size;
6663 }
6664 
6665 symbolS *
md_undefined_symbol(char * name ATTRIBUTE_UNUSED)6666 md_undefined_symbol (char *name ATTRIBUTE_UNUSED)
6667 {
6668   return NULL;
6669 }
6670 
6671 /* Functions concerning relocs.  */
6672 
6673 /* The location from which a PC relative jump should be calculated,
6674    given a PC relative reloc.  */
6675 
6676 long
md_pcrel_from_section(fixS * fixP,segT sec)6677 md_pcrel_from_section (fixS * fixP, segT sec)
6678 {
6679   if ((fixP->fx_addsy != (symbolS *) NULL
6680        && (! S_IS_DEFINED (fixP->fx_addsy)
6681 	   || S_GET_SEGMENT (fixP->fx_addsy) != sec))
6682       || metag_force_relocation (fixP))
6683     {
6684       /* The symbol is undefined (or is defined but not in this section).
6685 	 Let the linker figure it out.  */
6686       return 0;
6687     }
6688 
6689   return fixP->fx_frag->fr_address + fixP->fx_where;
6690 }
6691 
6692 /* Write a value out to the object file, using the appropriate endianness.  */
6693 
6694 void
md_number_to_chars(char * buf,valueT val,int n)6695 md_number_to_chars (char * buf, valueT val, int n)
6696 {
6697   number_to_chars_littleendian (buf, val, n);
6698 }
6699 
6700 /* Turn a string in input_line_pointer into a floating point constant of type
6701    type, and store the appropriate bytes in *litP.  The number of LITTLENUMS
6702    emitted is stored in *sizeP .  An error message is returned, or NULL on OK.
6703 */
6704 
6705 const char *
md_atof(int type,char * litP,int * sizeP)6706 md_atof (int type, char * litP, int * sizeP)
6707 {
6708   int              i;
6709   int              prec;
6710   LITTLENUM_TYPE   words [MAX_LITTLENUMS];
6711   char *           t;
6712 
6713   switch (type)
6714     {
6715     case 'f':
6716     case 'F':
6717     case 's':
6718     case 'S':
6719       prec = 2;
6720       break;
6721 
6722     case 'd':
6723     case 'D':
6724     case 'r':
6725     case 'R':
6726       prec = 4;
6727       break;
6728 
6729    /* FIXME: Some targets allow other format chars for bigger sizes here.  */
6730 
6731     default:
6732       * sizeP = 0;
6733       return _("Bad call to md_atof()");
6734     }
6735 
6736   t = atof_ieee (input_line_pointer, type, words);
6737   if (t)
6738     input_line_pointer = t;
6739   * sizeP = prec * sizeof (LITTLENUM_TYPE);
6740 
6741   for (i = 0; i < prec; i++)
6742     {
6743       md_number_to_chars (litP, (valueT) words[i],
6744 			  sizeof (LITTLENUM_TYPE));
6745       litP += sizeof (LITTLENUM_TYPE);
6746     }
6747 
6748   return 0;
6749 }
6750 
6751 /* If this function returns non-zero, it prevents the relocation
6752    against symbol(s) in the FIXP from being replaced with relocations
6753    against section symbols, and guarantees that a relocation will be
6754    emitted even when the value can be resolved locally.  */
6755 
6756 int
metag_force_relocation(fixS * fix)6757 metag_force_relocation (fixS * fix)
6758 {
6759   switch (fix->fx_r_type)
6760     {
6761     case BFD_RELOC_METAG_RELBRANCH_PLT:
6762     case BFD_RELOC_METAG_TLS_LE:
6763     case BFD_RELOC_METAG_TLS_IE:
6764     case BFD_RELOC_METAG_TLS_LDO:
6765     case BFD_RELOC_METAG_TLS_LDM:
6766     case BFD_RELOC_METAG_TLS_GD:
6767       return 1;
6768     default:
6769       ;
6770     }
6771 
6772   return generic_force_reloc (fix);
6773 }
6774 
6775 bool
metag_fix_adjustable(fixS * fixP)6776 metag_fix_adjustable (fixS * fixP)
6777 {
6778   if (fixP->fx_addsy == NULL)
6779     return 1;
6780 
6781   /* Prevent all adjustments to global symbols.  */
6782   if (S_IS_EXTERNAL (fixP->fx_addsy))
6783     return 0;
6784   if (S_IS_WEAK (fixP->fx_addsy))
6785     return 0;
6786 
6787   if (fixP->fx_r_type == BFD_RELOC_METAG_HI16_GOTOFF ||
6788       fixP->fx_r_type == BFD_RELOC_METAG_LO16_GOTOFF ||
6789       fixP->fx_r_type == BFD_RELOC_METAG_GETSET_GOTOFF ||
6790       fixP->fx_r_type == BFD_RELOC_METAG_GETSET_GOT ||
6791       fixP->fx_r_type == BFD_RELOC_METAG_HI16_GOTPC ||
6792       fixP->fx_r_type == BFD_RELOC_METAG_LO16_GOTPC ||
6793       fixP->fx_r_type == BFD_RELOC_METAG_HI16_PLT ||
6794       fixP->fx_r_type == BFD_RELOC_METAG_LO16_PLT ||
6795       fixP->fx_r_type == BFD_RELOC_METAG_RELBRANCH_PLT)
6796     return 0;
6797 
6798   /* We need the symbol name for the VTABLE entries.  */
6799   if (fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
6800       || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
6801     return 0;
6802 
6803   return 1;
6804 }
6805 
6806 /* Return an initial guess of the length by which a fragment must grow to
6807    hold a branch to reach its destination.
6808    Also updates fr_type/fr_subtype as necessary.
6809 
6810    Called just before doing relaxation.
6811    Any symbol that is now undefined will not become defined.
6812    The guess for fr_var is ACTUALLY the growth beyond fr_fix.
6813    Whatever we do to grow fr_fix or fr_var contributes to our returned value.
6814    Although it may not be explicit in the frag, pretend fr_var starts with a
6815    0 value.  */
6816 
6817 int
md_estimate_size_before_relax(fragS * fragP ATTRIBUTE_UNUSED,segT segment ATTRIBUTE_UNUSED)6818 md_estimate_size_before_relax (fragS * fragP ATTRIBUTE_UNUSED,
6819 			       segT    segment ATTRIBUTE_UNUSED)
6820 {
6821   /* No assembler relaxation is defined (or necessary) for this port.  */
6822   abort ();
6823 }
6824 
6825 /* *fragP has been relaxed to its final size, and now needs to have
6826    the bytes inside it modified to conform to the new size.
6827 
6828    Called after relaxation is finished.
6829    fragP->fr_type == rs_machine_dependent.
6830    fragP->fr_subtype is the subtype of what the address relaxed to.  */
6831 
6832 void
md_convert_frag(bfd * abfd ATTRIBUTE_UNUSED,segT sec ATTRIBUTE_UNUSED,fragS * fragP ATTRIBUTE_UNUSED)6833 md_convert_frag (bfd * abfd ATTRIBUTE_UNUSED, segT sec ATTRIBUTE_UNUSED,
6834 		 fragS * fragP ATTRIBUTE_UNUSED)
6835 {
6836   /* No assembler relaxation is defined (or necessary) for this port.  */
6837   abort ();
6838 }
6839 
6840 /* This is called from HANDLE_ALIGN in tc-metag.h.  */
6841 
6842 void
metag_handle_align(fragS * fragP)6843 metag_handle_align (fragS * fragP)
6844 {
6845   static unsigned char const noop[4] = { 0xfe, 0xff, 0xff, 0xa0 };
6846   int bytes, fix;
6847   char *p;
6848 
6849   if (fragP->fr_type != rs_align_code)
6850     return;
6851 
6852   bytes = fragP->fr_next->fr_address - fragP->fr_address - fragP->fr_fix;
6853   p = fragP->fr_literal + fragP->fr_fix;
6854   fix = 0;
6855 
6856   if (bytes & 3)
6857     {
6858       fix = bytes & 3;
6859       memset (p, 0, fix);
6860       p += fix;
6861       bytes -= fix;
6862     }
6863 
6864   while (bytes >= 4)
6865     {
6866       memcpy (p, noop, 4);
6867       p += 4;
6868       bytes -= 4;
6869       fix += 4;
6870     }
6871 
6872   fragP->fr_fix += fix;
6873   fragP->fr_var = 4;
6874 }
6875 
6876 static char *
metag_end_of_match(char * cont,const char * what)6877 metag_end_of_match (char * cont, const char * what)
6878 {
6879   int len = strlen (what);
6880 
6881   if (strncasecmp (cont, what, strlen (what)) == 0
6882       && ! is_part_of_name (cont[len]))
6883     return cont + len;
6884 
6885   return NULL;
6886 }
6887 
6888 int
metag_parse_name(char const * name,expressionS * exprP,enum expr_mode mode,char * nextcharP)6889 metag_parse_name (char const * name, expressionS * exprP, enum expr_mode mode,
6890 		  char * nextcharP)
6891 {
6892   char *next = input_line_pointer;
6893   char *next_end;
6894   int reloc_type;
6895   operatorT op_type;
6896   segT segment;
6897 
6898   exprP->X_op_symbol = NULL;
6899   exprP->X_md = BFD_RELOC_UNUSED;
6900 
6901   if (strcmp (name, GOT_NAME) == 0)
6902     {
6903       if (! GOT_symbol)
6904 	GOT_symbol = symbol_find_or_make (name);
6905 
6906       exprP->X_add_symbol = GOT_symbol;
6907     no_suffix:
6908       /* If we have an absolute symbol or a
6909 	 reg, then we know its value now.  */
6910       segment = S_GET_SEGMENT (exprP->X_add_symbol);
6911       if (mode != expr_defer && segment == absolute_section)
6912 	{
6913 	  exprP->X_op = O_constant;
6914 	  exprP->X_add_number = S_GET_VALUE (exprP->X_add_symbol);
6915 	  exprP->X_add_symbol = NULL;
6916 	}
6917       else if (mode != expr_defer && segment == reg_section)
6918 	{
6919 	  exprP->X_op = O_register;
6920 	  exprP->X_add_number = S_GET_VALUE (exprP->X_add_symbol);
6921 	  exprP->X_add_symbol = NULL;
6922 	}
6923       else
6924 	{
6925 	  exprP->X_op = O_symbol;
6926 	  exprP->X_add_number = 0;
6927 	}
6928 
6929       return 1;
6930     }
6931 
6932   exprP->X_add_symbol = symbol_find_or_make (name);
6933 
6934   if (*nextcharP != '@')
6935     goto no_suffix;
6936   else if ((next_end = metag_end_of_match (next + 1, "GOTOFF")))
6937     {
6938       reloc_type = BFD_RELOC_METAG_GOTOFF;
6939       op_type = O_PIC_reloc;
6940     }
6941   else if ((next_end = metag_end_of_match (next + 1, "GOT")))
6942     {
6943       reloc_type = BFD_RELOC_METAG_GETSET_GOT;
6944       op_type = O_PIC_reloc;
6945     }
6946   else if ((next_end = metag_end_of_match (next + 1, "PLT")))
6947     {
6948       reloc_type = BFD_RELOC_METAG_PLT;
6949       op_type = O_PIC_reloc;
6950     }
6951   else if ((next_end = metag_end_of_match (next + 1, "TLSGD")))
6952     {
6953       reloc_type = BFD_RELOC_METAG_TLS_GD;
6954       op_type = O_PIC_reloc;
6955     }
6956   else if ((next_end = metag_end_of_match (next + 1, "TLSLDM")))
6957     {
6958       reloc_type = BFD_RELOC_METAG_TLS_LDM;
6959       op_type = O_PIC_reloc;
6960     }
6961   else if ((next_end = metag_end_of_match (next + 1, "TLSLDO")))
6962     {
6963       reloc_type = BFD_RELOC_METAG_TLS_LDO;
6964       op_type = O_PIC_reloc;
6965     }
6966   else if ((next_end = metag_end_of_match (next + 1, "TLSIE")))
6967     {
6968       reloc_type = BFD_RELOC_METAG_TLS_IE;
6969       op_type = O_PIC_reloc;
6970     }
6971   else if ((next_end = metag_end_of_match (next + 1, "TLSIENONPIC")))
6972     {
6973       reloc_type = BFD_RELOC_METAG_TLS_IENONPIC;
6974       op_type = O_PIC_reloc;	/* FIXME: is this correct? */
6975     }
6976   else if ((next_end = metag_end_of_match (next + 1, "TLSLE")))
6977     {
6978       reloc_type = BFD_RELOC_METAG_TLS_LE;
6979       op_type = O_PIC_reloc;
6980     }
6981   else
6982     goto no_suffix;
6983 
6984   *input_line_pointer = *nextcharP;
6985   input_line_pointer = next_end;
6986   *nextcharP = *input_line_pointer;
6987   *input_line_pointer = '\0';
6988 
6989   exprP->X_op = op_type;
6990   exprP->X_add_number = 0;
6991   exprP->X_md = reloc_type;
6992 
6993   return 1;
6994 }
6995 
6996 /* If while processing a fixup, a reloc really needs to be created
6997    then it is done here.  */
6998 
6999 arelent *
tc_gen_reloc(asection * seg ATTRIBUTE_UNUSED,fixS * fixp)7000 tc_gen_reloc (asection *seg ATTRIBUTE_UNUSED, fixS *fixp)
7001 {
7002   arelent *reloc;
7003 
7004   reloc		      = XNEW (arelent);
7005   reloc->sym_ptr_ptr  = XNEW (asymbol *);
7006   *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
7007   reloc->address      = fixp->fx_frag->fr_address + fixp->fx_where;
7008 
7009   reloc->addend = fixp->fx_offset;
7010   reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type);
7011 
7012   if (reloc->howto == (reloc_howto_type *) NULL)
7013     {
7014       as_bad_where (fixp->fx_file, fixp->fx_line,
7015 		    /* xgettext:c-format.  */
7016 		    _("reloc %d not supported by object file format"),
7017 		    (int) fixp->fx_r_type);
7018 
7019       xfree (reloc);
7020 
7021       return NULL;
7022     }
7023 
7024   return reloc;
7025 }
7026 
7027 static unsigned int
md_chars_to_number(char * val,int n)7028 md_chars_to_number (char *val, int n)
7029 {
7030   unsigned int retval;
7031   unsigned char * where = (unsigned char *) val;
7032 
7033   for (retval = 0; n--;)
7034     {
7035       retval <<= 8;
7036       retval |= where[n];
7037     }
7038   return retval;
7039 }
7040 
7041 void
md_apply_fix(fixS * fixP,valueT * valP,segT seg ATTRIBUTE_UNUSED)7042 md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
7043 {
7044   char *buf = fixP->fx_where + fixP->fx_frag->fr_literal;
7045   int value = (int)*valP;
7046 
7047   switch (fixP->fx_r_type)
7048     {
7049     case BFD_RELOC_METAG_TLS_GD:
7050     case BFD_RELOC_METAG_TLS_LE_HI16:
7051     case BFD_RELOC_METAG_TLS_LE_LO16:
7052     case BFD_RELOC_METAG_TLS_IE:
7053     case BFD_RELOC_METAG_TLS_IENONPIC_HI16:
7054     case BFD_RELOC_METAG_TLS_IENONPIC_LO16:
7055     case BFD_RELOC_METAG_TLS_LDM:
7056     case BFD_RELOC_METAG_TLS_LDO_HI16:
7057     case BFD_RELOC_METAG_TLS_LDO_LO16:
7058       S_SET_THREAD_LOCAL (fixP->fx_addsy);
7059       /* Fall through */
7060 
7061     case BFD_RELOC_METAG_HIADDR16:
7062     case BFD_RELOC_METAG_LOADDR16:
7063     case BFD_RELOC_VTABLE_INHERIT:
7064     case BFD_RELOC_VTABLE_ENTRY:
7065       fixP->fx_done = false;
7066       break;
7067 
7068     case BFD_RELOC_METAG_REL8:
7069       if (!within_unsigned_range (value, IMM8_BITS))
7070 	{
7071 	  as_bad_where (fixP->fx_file, fixP->fx_line,
7072 			"rel8 out of range %d", value);
7073 	}
7074       else
7075 	{
7076 	  unsigned int newval;
7077 	  newval = md_chars_to_number (buf, 4);
7078 	  newval = (newval & 0xffffc03f) | ((value & IMM8_MASK) << 6);
7079 	  md_number_to_chars (buf, newval, 4);
7080 	}
7081       break;
7082     case BFD_RELOC_METAG_REL16:
7083       if (!within_unsigned_range (value, IMM16_BITS))
7084 	{
7085 	  as_bad_where (fixP->fx_file, fixP->fx_line,
7086 			"rel16 out of range %d", value);
7087 	}
7088       else
7089 	{
7090 	  unsigned int newval;
7091 	  newval = md_chars_to_number (buf, 4);
7092 	  newval = (newval & 0xfff80007) | ((value & IMM16_MASK) << 3);
7093 	  md_number_to_chars (buf, newval, 4);
7094 	}
7095       break;
7096 
7097     case BFD_RELOC_8:
7098       md_number_to_chars (buf, value, 1);
7099       break;
7100     case BFD_RELOC_16:
7101       md_number_to_chars (buf, value, 2);
7102       break;
7103     case BFD_RELOC_32:
7104       md_number_to_chars (buf, value, 4);
7105       break;
7106     case BFD_RELOC_64:
7107       md_number_to_chars (buf, value, 8);
7108       break;
7109 
7110     case BFD_RELOC_METAG_RELBRANCH:
7111       if (!value)
7112 	break;
7113 
7114       value = value / 4;
7115 
7116       if (!within_signed_range (value, IMM19_BITS))
7117 	{
7118 	  as_bad_where (fixP->fx_file, fixP->fx_line,
7119 			"relbranch out of range %d", value);
7120 	}
7121       else
7122 	{
7123 	  unsigned int newval;
7124 	  newval = md_chars_to_number (buf, 4);
7125 	  newval = (newval & 0xff00001f) | ((value & IMM19_MASK) << 5);
7126 	  md_number_to_chars (buf, newval, 4);
7127 	}
7128 	break;
7129     default:
7130       break;
7131     }
7132 
7133   if (fixP->fx_addsy == NULL)
7134     fixP->fx_done = true;
7135 }
7136