Re: ld plugin bfd_make_readable leak
[binutils-gdb.git] / gas / config / tc-metag.c
blobf4364356d8f5e18ca03c5ba2c8cfb3f76ab0a852
1 /* tc-metag.c -- Assembler for the Imagination Technologies Meta.
2 Copyright (C) 2013-2025 Free Software Foundation, Inc.
3 Contributed by Imagination Technologies Ltd.
5 This file is part of GAS, the GNU Assembler.
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.
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.
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. */
22 #include "as.h"
23 #include "subsegs.h"
24 #include "symcat.h"
25 #include "safe-ctype.h"
26 #include "hashtab.h"
28 #include <stdio.h>
30 #include "opcode/metag.h"
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[] = "[";
39 static char register_chars[256];
40 static char mnemonic_chars[256];
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) == ' ')
47 #define FPU_PREFIX_CHAR 'f'
48 #define DSP_PREFIX_CHAR 'd'
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"
55 #define FPU_DOUBLE_CHAR 'd'
56 #define FPU_PAIR_CHAR 'l'
58 #define DSP_DUAL_CHAR 'l'
60 #define END_OF_INSN '\0'
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
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 '#'
73 #define COMMA ','
74 #define PLUS '+'
75 #define MINUS '-'
77 /* Short units are those that can be encoded with 2 bits. */
78 #define SHORT_UNITS "D0, D1, A0 or A1"
80 static unsigned int mcpu_opt = CoreMeta12;
81 static unsigned int mfpu_opt = 0;
82 static unsigned int mdsp_opt = 0;
84 const char md_shortopts[] = "m:";
86 const struct option md_longopts[] =
88 {NULL, no_argument, NULL, 0}
90 const size_t md_longopts_size = sizeof (md_longopts);
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;
99 #define GOT_NAME "__GLOBAL_OFFSET_TABLE__"
100 symbolS * GOT_symbol;
102 enum fpu_insn_width {
103 FPU_WIDTH_SINGLE,
104 FPU_WIDTH_DOUBLE,
105 FPU_WIDTH_PAIR,
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'
113 #define FPU_ACTION_ABS 0x1
114 #define FPU_ACTION_INV 0x2
115 #define FPU_ACTION_QUIET 0x4
116 #define FPU_ACTION_ZERO 0x8
118 enum dsp_insn_width {
119 DSP_WIDTH_SINGLE,
120 DSP_WIDTH_DUAL,
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'
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
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'
150 #define DSP_DAOPPAME_8 0x1
151 #define DSP_DAOPPAME_16 0x2
152 #define DSP_DAOPPAME_TEMP 0x4
153 #define DSP_DAOPPAME_HIGH 0x8
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;
162 /* Instruction bits. */
163 unsigned int bits;
164 /* Size of the instruction in bytes. */
165 size_t len;
167 /* FPU instruction encoding. */
168 enum fpu_insn_width fpu_width;
169 unsigned int fpu_action_flags;
171 /* DSP instruction encoding. */
172 enum dsp_insn_width dsp_width;
173 unsigned int dsp_action_flags;
174 unsigned int dsp_daoppame_flags;
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;
183 /* Structure holding information about a parsed addressing mode. */
184 typedef struct {
185 const metag_reg *base_reg;
186 const metag_reg *offset_reg;
188 expressionS exp;
190 enum bfd_reloc_code_real reloc_type;
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;
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;
208 /* Parse an instruction that takes no operands. */
209 static const char *
210 parse_none (const char *line, metag_insn *insn,
211 const insn_template *template)
213 insn->bits = template->meta_opcode;
214 insn->len = 4;
215 return line;
218 /* Return the next non-whitespace character in LINE or NULL. */
219 static const char *
220 skip_whitespace (const char *line)
222 const char *l = line;
224 if (is_whitespace_char (*l))
226 l++;
229 return l;
232 /* Return the next non-space character in LINE or NULL. */
233 static const char *
234 skip_space (const char *line)
236 const char *l = line;
238 if (is_space_char (*l))
240 l++;
243 return l;
246 /* Return the character after the current one in LINE if the current
247 character is a comma, otherwise NULL. */
248 static const char *
249 skip_comma (const char *line)
251 const char *l = line;
253 if (l == NULL || *l != COMMA)
254 return NULL;
256 l++;
258 return l;
261 /* Return the metag_reg struct corresponding to NAME or NULL if no such
262 register exists. */
263 static const metag_reg *
264 parse_gp_reg (const char *name)
266 const metag_reg *reg;
267 metag_reg entry;
269 entry.name = name;
271 reg = (const metag_reg *) htab_find (reg_htab, &entry);
273 return reg;
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 *
280 parse_gp_regs_list (const char *line, const metag_reg **regs, size_t count,
281 size_t *regs_read)
283 const char *l = line;
284 char reg_buf[MAX_REG_LEN];
285 int seen_regs = 0;
286 size_t i;
288 for (i = 0; i < count; i++)
290 size_t len = 0;
291 const char *next;
293 next = l;
295 if (i > 0)
297 l = skip_comma (l);
298 if (l == NULL)
300 *regs_read = seen_regs;
301 return next;
305 while (is_register_char (*l))
307 reg_buf[len] = *l;
308 l++;
309 len++;
310 if (!(len < MAX_REG_LEN))
311 return NULL;
314 reg_buf[len] = '\0';
316 if (len)
318 const metag_reg *reg = parse_gp_reg (reg_buf);
320 if (!reg)
322 *regs_read = seen_regs;
323 return next;
325 else
327 regs[i] = reg;
328 seen_regs++;
331 else
333 *regs_read = seen_regs;
334 return next;
338 *regs_read = seen_regs;
339 return l;
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 *
345 parse_gp_regs (const char *line, const metag_reg **regs, size_t count)
347 const char *l = line;
348 size_t regs_read = 0;
350 l = parse_gp_regs_list (l, regs, count, &regs_read);
352 if (regs_read != count)
353 return NULL;
354 else
355 return l;
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 *
361 parse_fpu_regs (const char *line, const metag_reg **regs, size_t count)
363 const char *l = line;
364 size_t regs_read = 0;
366 l = parse_gp_regs_list (l, regs, count, &regs_read);
368 if (regs_read != count)
369 return NULL;
370 else
372 size_t i;
373 for (i = 0; i < count; i++)
375 if (regs[i]->unit != UNIT_FX)
376 return NULL;
378 return l;
382 /* Return TRUE if REG1 and REG2 are in paired units. */
383 static bool
384 is_unit_pair (const metag_reg *reg1, const metag_reg *reg2)
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;
396 return false;
399 /* Return TRUE if REG1 and REG2 form a register pair. */
400 static bool
401 is_reg_pair (const metag_reg *reg1, const metag_reg *reg2)
403 if (reg1->unit == UNIT_FX &&
404 reg2->unit == UNIT_FX &&
405 reg2->no == reg1->no + 1)
406 return true;
408 if (reg1->no != reg2->no)
409 return false;
411 return is_unit_pair (reg1, reg2);
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 *
417 parse_pair_gp_regs (const char *line, const metag_reg **regs)
419 const char *l = line;
421 l = parse_gp_regs (line, regs, 2);
423 if (l == NULL)
425 l = parse_gp_regs (line, regs, 1);
427 if (l == NULL)
428 return NULL;
430 if (regs[0]->unit == UNIT_RD)
431 return l;
432 else
433 return NULL;
436 if (is_reg_pair (regs[0], regs[1]))
437 return l;
439 return NULL;
442 /* Parse a unit-to-unit MOV instruction. */
443 static const char *
444 parse_mov_u2u (const char *line, metag_insn *insn,
445 const insn_template *template)
447 const metag_reg *regs[2];
449 line = parse_gp_regs (line, regs, 2);
451 if (line == NULL)
452 return NULL;
454 if (!mfpu_opt && (regs[0]->unit == UNIT_FX || regs[1]->unit == UNIT_FX))
456 as_bad (_("no floating point unit specified"));
457 return NULL;
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;
469 /* Parse a MOV to port instruction. */
470 static const char *
471 parse_mov_port (const char *line, metag_insn *insn,
472 const insn_template *template)
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];
479 if (is_movl)
480 l = parse_gp_regs (l, dest_regs, 2);
481 else
482 l = parse_gp_regs (l, dest_regs, 1);
484 if (l == NULL)
485 return NULL;
487 if (template->insn_type == INSN_FPU && dest_regs[0]->unit != UNIT_FX)
488 return NULL;
490 l = skip_comma (l);
492 if (l == NULL ||
493 *l == END_OF_INSN)
494 return NULL;
496 l = parse_gp_regs (l, port_regs, 1);
498 if (l == NULL)
499 return NULL;
501 if (port_regs[0]->unit != UNIT_RD ||
502 port_regs[0]->no != 0)
503 return NULL;
505 if (is_movl)
507 if (!is_unit_pair (dest_regs[0], dest_regs[1]))
508 return NULL;
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));
515 else
516 insn->bits = (template->meta_opcode |
517 (dest_regs[0]->no << 14) |
518 (dest_regs[0]->unit << 5));
520 insn->len = 4;
521 return l;
524 /* Parse a MOVL to TTREC instruction. */
525 static const char *
526 parse_movl_ttrec (const char *line, metag_insn *insn,
527 const insn_template *template)
529 const char *l = line;
530 const metag_reg *src_regs[2];
531 const metag_reg *dest_regs[1];
533 l = parse_gp_regs (l, dest_regs, 1);
535 if (l == NULL)
536 return NULL;
538 if (dest_regs[0]->unit != UNIT_TT ||
539 dest_regs[0]->no != 3)
540 return NULL;
542 l = skip_comma (l);
544 if (l == NULL ||
545 *l == END_OF_INSN)
546 return NULL;
548 l = parse_gp_regs (l, src_regs, 2);
550 if (l == NULL)
551 return NULL;
553 if (!is_unit_pair (src_regs[0], src_regs[1]))
554 return NULL;
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));
561 insn->len = 4;
562 return l;
565 /* Parse an incrementing or decrementing addressing mode. */
566 static const char *
567 parse_addr_incr_op (const char *line, metag_addr *addr)
569 const char *l = line;
570 const char *ll;
572 ll = l + 1;
574 if (*l == PLUS &&
575 *ll == PLUS)
577 addr->update = 1;
578 ll++;
579 return ll;
581 else if (*l == MINUS &&
582 *ll == MINUS)
584 addr->update = 1;
585 addr->negate = 1;
586 ll++;
587 return ll;
589 return NULL;
592 /* Parse an pre-incrementing or pre-decrementing addressing mode. */
593 static const char *
594 parse_addr_pre_incr_op (const char *line, metag_addr *addr)
596 return parse_addr_incr_op (line, addr);
599 /* Parse an post-incrementing or post-decrementing addressing mode. */
600 static const char *
601 parse_addr_post_incr_op (const char *line, metag_addr *addr)
603 const char *l;
605 l = parse_addr_incr_op (line, addr);
607 if (l == NULL)
608 return NULL;
610 addr->post_increment = 1;
612 return l;
615 /* Parse an infix addressing mode. */
616 static const char *
617 parse_addr_op (const char *line, metag_addr *addr)
619 const char *l = line;
620 const char *ll;
622 ll = l + 1;
624 if (*l == PLUS)
626 if (*ll == PLUS)
628 addr->update = 1;
629 ll++;
630 return ll;
632 l++;
633 return l;
635 return NULL;
638 /* Parse the immediate portion of an addressing mode. */
639 static const char *
640 parse_imm_addr (const char *line, metag_addr *addr)
642 const char *l = line;
643 char *save_input_line_pointer;
644 expressionS *exp = &addr->exp;
646 /* Skip #. */
647 if (*l == '#')
648 l++;
649 else
650 return NULL;
652 save_input_line_pointer = input_line_pointer;
653 input_line_pointer = (char *) l;
655 expression (exp);
657 l = input_line_pointer;
658 input_line_pointer = save_input_line_pointer;
660 if (exp->X_op == O_absent || exp->X_op == O_big)
662 return NULL;
664 else if (exp->X_op == O_constant)
666 return l;
668 else
670 if (exp->X_op == O_PIC_reloc &&
671 exp->X_md == BFD_RELOC_METAG_GETSET_GOT)
673 exp->X_op = O_symbol;
674 addr->reloc_type = BFD_RELOC_METAG_GETSET_GOT;
676 else if (exp->X_op == O_PIC_reloc &&
677 exp->X_md == BFD_RELOC_METAG_TLS_IE)
679 exp->X_op = O_symbol;
680 addr->reloc_type = BFD_RELOC_METAG_TLS_IE;
682 else if (exp->X_op == O_PIC_reloc &&
683 exp->X_md == BFD_RELOC_METAG_GOTOFF)
685 exp->X_op = O_symbol;
686 addr->reloc_type = BFD_RELOC_METAG_GETSET_GOTOFF;
688 else
689 addr->reloc_type = BFD_RELOC_METAG_GETSETOFF;
690 return l;
694 /* Parse the offset portion of an addressing mode (register or immediate). */
695 static const char *
696 parse_addr_offset (const char *line, metag_addr *addr, int size)
698 const char *l = line;
699 const metag_reg *regs[1];
701 if (*l == IMM_CHAR)
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 = '+';
708 if (ppp)
709 *ppp = '\0';
711 l = parse_imm_addr (l, addr);
713 if (ppp)
714 *ppp = ppch;
716 if (l == NULL)
717 return NULL;
719 if (addr->exp.X_add_number % size)
721 as_bad (_("offset must be a multiple of %d"), size);
722 return NULL;
725 addr->immediate = 1;
726 return l;
728 else
730 l = parse_gp_regs (l, regs, 1);
732 if (l == NULL)
733 return NULL;
735 if (regs[0]->unit != addr->base_reg->unit)
737 as_bad (_("offset and base must be from the same unit"));
738 return NULL;
741 addr->offset_reg = regs[0];
742 return l;
746 /* Parse an addressing mode. */
747 static const char *
748 parse_addr (const char *line, metag_addr *addr, unsigned int size)
750 const char *l = line;
751 const char *ll;
752 const metag_reg *regs[1];
754 /* Skip opening square bracket. */
755 l++;
757 ll = parse_addr_pre_incr_op (l, addr);
759 if (ll != NULL)
760 l = ll;
762 l = parse_gp_regs (l, regs, 1);
764 if (l == NULL)
765 return NULL;
767 addr->base_reg = regs[0];
769 if (*l == ADDR_END_CHAR)
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)
776 /* We have a pre increment/decrement. */
777 addr->exp.X_add_number = size;
779 else
781 /* Simple register with no offset (0 immediate). */
782 addr->exp.X_add_number = 0;
784 addr->immediate = 1;
785 l++;
786 return l;
789 /* We already had a pre increment/decrement. */
790 if (addr->update == 1)
791 return NULL;
793 ll = parse_addr_post_incr_op (l, addr);
795 if (ll && *ll == ADDR_END_CHAR)
797 if (addr->update == 1)
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;
806 addr->immediate = 1;
807 ll++;
808 return ll;
811 addr->post_increment = 0;
813 l = parse_addr_op (l, addr);
815 if (l == NULL)
816 return NULL;
818 l = parse_addr_offset (l, addr, size);
820 if (l == NULL)
821 return NULL;
823 if (*l == ADDR_END_CHAR)
825 l++;
826 return l;
829 /* We already had a pre increment/decrement. */
830 if (addr->update == 1)
831 return NULL;
833 l = parse_addr_post_incr_op (l, addr);
835 if (l == NULL)
836 return NULL;
838 if (*l == ADDR_END_CHAR)
840 l++;
841 return l;
844 return NULL;
847 /* Parse a GET or pipeline MOV instruction. */
848 static const char *
849 parse_get (const char *line, const metag_reg **regs, metag_addr *addr,
850 unsigned int size, bool is_mov)
852 const char *l = line;
854 if (size == 8)
856 l = parse_pair_gp_regs (l, regs);
858 if (l == NULL)
859 return NULL;
861 else
863 l = parse_gp_regs (l, regs, 1);
865 if (l == NULL)
867 if (!is_mov)
868 as_bad (_("invalid destination register"));
869 return NULL;
873 l = skip_comma (l);
875 if (l == NULL ||
876 *l == END_OF_INSN)
877 return NULL;
879 l = parse_addr (l, addr, size);
881 if (l == NULL)
883 if (!is_mov)
884 as_bad (_("invalid memory operand"));
885 return NULL;
888 return l;
891 /* Parse a SET instruction. */
892 static const char *
893 parse_set (const char *line, const metag_reg **regs, metag_addr *addr,
894 unsigned int size)
896 const char *l = line;
898 l = parse_addr (l, addr, size);
900 if (l == NULL)
902 as_bad (_("invalid memory operand"));
903 return NULL;
906 l = skip_comma (l);
908 if (l == NULL ||
909 *l == END_OF_INSN)
910 return NULL;
912 if (size == 8)
914 const char *ll = l;
916 ll = parse_pair_gp_regs (l, regs);
918 if (ll == NULL)
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);
924 if (l == NULL ||
925 regs[0]->unit != UNIT_RD)
927 return NULL;
930 else
931 l = ll;
933 else
935 l = parse_gp_regs (l, regs, 1);
937 if (l == NULL)
939 as_bad (_("invalid source register"));
940 return NULL;
944 return l;
947 /* Check a signed integer value can be represented in the given number
948 of bits. */
949 static bool
950 within_signed_range (int value, unsigned int bits)
952 int min_val = -(1 << (bits - 1));
953 int max_val = (1 << (bits - 1)) - 1;
954 return (value <= max_val) && (value >= min_val);
957 /* Check an unsigned integer value can be represented in the given number
958 of bits. */
959 static bool
960 within_unsigned_range (unsigned int value, unsigned int bits)
962 return value < (unsigned int)(1 << bits);
965 /* Return TRUE if UNIT can be expressed using a short code. */
966 static bool
967 is_short_unit (enum metag_unit unit)
969 switch (unit)
971 case UNIT_A0:
972 case UNIT_A1:
973 case UNIT_D0:
974 case UNIT_D1:
975 return true;
976 default:
977 return false;
981 /* Copy reloc data from ADDR to INSN. */
982 static void
983 copy_addr_reloc (metag_insn *insn, metag_addr *addr)
985 memcpy (&insn->reloc_exp, &addr->exp, sizeof(insn->reloc_exp));
986 insn->reloc_type = addr->reloc_type;
989 /* Parse a GET, SET or pipeline MOV instruction. */
990 static const char *
991 parse_get_set (const char *line, metag_insn *insn,
992 const insn_template *template)
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;
1001 memset(&addr, 0, sizeof(addr));
1002 addr.reloc_type = BFD_RELOC_UNUSED;
1004 if (is_get)
1006 bool is_mov = startswith (template->name, "MOV");
1008 l = parse_get (l, regs, &addr, size, is_mov);
1010 if (l == NULL)
1011 return NULL;
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))
1024 as_bad (_("invalid destination unit"));
1025 return NULL;
1028 if (regs[0]->unit == UNIT_RD)
1030 if (regs[0]->no == 0)
1032 as_bad (_("mov cannot use RD port as destination"));
1033 return NULL;
1037 reg_no = regs[0]->no;
1039 else
1041 l = parse_set (l, regs, &addr, size);
1043 if (l == NULL)
1044 return NULL;
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))
1057 as_bad (_("invalid source unit"));
1058 return NULL;
1061 if (addr.immediate == 0 &&
1062 (regs[0]->unit == addr.base_reg->unit ||
1063 (size == 8 && is_unit_pair (regs[0], addr.base_reg))))
1065 as_bad (_("source and address units must not be shared for this addressing mode"));
1066 return NULL;
1069 if (regs[0]->unit == UNIT_RD)
1071 if (regs[0]->no != 0)
1073 as_bad (_("set can only use RD port as source"));
1074 return NULL;
1076 reg_no = 16;
1078 else
1079 reg_no = regs[0]->no;
1082 insn->bits = (template->meta_opcode |
1083 (reg_no << 19) |
1084 (regs[0]->unit << 1));
1086 if (!is_short_unit (addr.base_reg->unit))
1088 as_bad (_("base unit must be one of %s"), SHORT_UNITS);
1089 return NULL;
1092 insn->bits |= ((addr.base_reg->no << 14) |
1093 ((addr.base_reg->unit & SHORT_UNIT_MASK) << 5));
1095 if (addr.immediate)
1097 int offset = addr.exp.X_add_number;
1099 copy_addr_reloc (insn, &addr);
1101 if (addr.negate)
1102 offset = -offset;
1104 offset = offset / (int)size;
1106 if (!within_signed_range (offset, GET_SET_IMM_BITS))
1108 /* We already tried to encode as an extended GET/SET. */
1109 as_bad (_("offset value out of range"));
1110 return NULL;
1113 offset = offset & GET_SET_IMM_MASK;
1115 insn->bits |= (0x1 << 25);
1116 insn->bits |= (offset << 8);
1118 else
1120 insn->bits |= (addr.offset_reg->no << 9);
1123 if (addr.update)
1124 insn->bits |= (0x1 << 7);
1126 if (addr.post_increment)
1127 insn->bits |= 0x1;
1129 insn->len = 4;
1130 return l;
1133 /* Parse an extended GET or SET instruction. */
1134 static const char *
1135 parse_get_set_ext (const char *line, metag_insn *insn,
1136 const insn_template *template)
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;
1146 memset(&addr, 0, sizeof(addr));
1147 addr.reloc_type = BFD_RELOC_UNUSED;
1149 if (is_get || is_mov)
1151 l = parse_get (l, regs, &addr, size, is_mov);
1153 else
1155 l = parse_set (l, regs, &addr, size);
1158 if (l == NULL)
1159 return NULL;
1161 /* Extended GET/SET does not support incrementing addressing. */
1162 if (addr.update)
1163 return NULL;
1165 if (is_mov)
1167 if (regs[0]->unit != UNIT_RD)
1169 as_bad (_("destination unit must be RD"));
1170 return NULL;
1172 reg_unit = 0;
1174 else
1176 if (!is_short_unit (regs[0]->unit))
1178 return NULL;
1180 reg_unit = regs[0]->unit;
1183 insn->bits = (template->meta_opcode |
1184 (regs[0]->no << 19) |
1185 ((reg_unit & SHORT_UNIT_MASK) << 3));
1187 if (!is_short_unit (addr.base_reg->unit))
1189 as_bad (_("base unit must be one of %s"), SHORT_UNITS);
1190 return NULL;
1193 if (addr.base_reg->no > 1)
1195 return NULL;
1198 insn->bits |= ((addr.base_reg->no & EXT_BASE_REG_MASK) |
1199 ((addr.base_reg->unit & SHORT_UNIT_MASK) << 5));
1201 if (addr.immediate)
1203 int offset = addr.exp.X_add_number;
1205 copy_addr_reloc (insn, &addr);
1207 if (addr.negate)
1208 offset = -offset;
1210 offset = offset / (int)size;
1212 if (!within_signed_range (offset, GET_SET_EXT_IMM_BITS))
1214 /* Parsing as a standard GET/SET provides a smaller offset. */
1215 as_bad (_("offset value out of range"));
1216 return NULL;
1219 offset = offset & GET_SET_EXT_IMM_MASK;
1221 insn->bits |= (offset << 7);
1223 else
1225 return NULL;
1228 insn->len = 4;
1229 return l;
1232 /* Parse an MGET or MSET instruction addressing mode. */
1233 static const char *
1234 parse_mget_mset_addr (const char *line, metag_addr *addr)
1236 const char *l = line;
1237 const char *ll;
1238 const metag_reg *regs[1];
1240 /* Skip opening square bracket. */
1241 l++;
1243 l = parse_gp_regs (l, regs, 1);
1245 if (l == NULL)
1246 return NULL;
1248 addr->base_reg = regs[0];
1250 ll = parse_addr_post_incr_op (l, addr);
1252 if (ll != NULL)
1253 l = ll;
1255 if (addr->negate == 1)
1256 return NULL;
1258 if (*l == ADDR_END_CHAR)
1260 l++;
1261 return l;
1264 return NULL;
1267 /* Parse an MGET instruction. */
1268 static const char *
1269 parse_mget (const char *line, const metag_reg **regs, metag_addr *addr,
1270 size_t *regs_read)
1272 const char *l = line;
1274 l = parse_gp_regs_list (l, regs, MGET_MSET_MAX_REGS, regs_read);
1276 if (l == NULL ||
1277 *regs_read == 0)
1279 as_bad (_("invalid destination register list"));
1280 return NULL;
1283 l = skip_comma (l);
1285 if (l == NULL ||
1286 *l == END_OF_INSN)
1287 return NULL;
1289 l = parse_mget_mset_addr (l, addr);
1291 if (l == NULL)
1293 as_bad (_("invalid memory operand"));
1294 return NULL;
1297 return l;
1300 /* Parse an MSET instruction. */
1301 static const char *
1302 parse_mset (const char *line, const metag_reg **regs, metag_addr *addr,
1303 size_t *regs_read)
1305 const char *l = line;
1307 l = parse_mget_mset_addr (l, addr);
1309 if (l == NULL)
1311 as_bad (_("invalid memory operand"));
1312 return NULL;
1315 l = skip_comma (l);
1317 if (l == NULL ||
1318 *l == END_OF_INSN)
1319 return NULL;
1321 l = parse_gp_regs_list (l, regs, MGET_MSET_MAX_REGS, regs_read);
1323 if (l == NULL ||
1324 *regs_read == 0)
1326 as_bad (_("invalid source register list"));
1327 return NULL;
1330 return l;
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
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)
1342 unsigned int reg_unit = regs[0]->unit;
1343 size_t i;
1345 for (i = 0; i < regs_read; i++)
1347 if (is_fpu)
1349 if (is_64bit && regs[i]->no % 2)
1351 as_bad (_("register list must be even numbered"));
1352 return false;
1355 else if (regs[i]->unit != reg_unit)
1357 as_bad (_("register list must be from the same unit"));
1358 return false;
1361 if (regs[i]->no < *lowest_reg)
1362 *lowest_reg = regs[i]->no;
1365 for (i = 0; i < regs_read; i++)
1367 unsigned int next_bit, next_reg;
1368 if (regs[i]->no == *lowest_reg)
1369 continue;
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));
1376 next_bit = (1 << next_reg);
1378 if (*rmask & next_bit)
1380 as_bad (_("register list must not contain duplicates"));
1381 return false;
1384 *rmask |= next_bit;
1387 return true;
1390 /* Parse an MGET or MSET instruction. */
1391 static const char *
1392 parse_mget_mset (const char *line, metag_insn *insn,
1393 const insn_template *template)
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;
1404 memset(&addr, 0, sizeof(addr));
1405 addr.reloc_type = BFD_RELOC_UNUSED;
1407 if (is_get)
1409 l = parse_mget (l, regs, &addr, &regs_read);
1411 else
1413 l = parse_mset (l, regs, &addr, &regs_read);
1416 if (l == NULL)
1417 return NULL;
1419 if (!check_rmask (regs, regs_read, is_fpu, is_64bit, &lowest_reg, &rmask))
1420 return NULL;
1422 reg_unit = regs[0]->unit;
1424 if (is_fpu)
1426 if (reg_unit != UNIT_FX)
1427 return NULL;
1429 reg_unit = 0;
1431 else if (reg_unit == UNIT_FX)
1432 return NULL;
1434 insn->bits = (template->meta_opcode |
1435 (lowest_reg << 19) |
1436 ((reg_unit & SHORT_UNIT_MASK) << 3));
1438 if (!is_short_unit (addr.base_reg->unit))
1440 as_bad (_("base unit must be one of %s"), SHORT_UNITS);
1441 return NULL;
1444 insn->bits |= ((addr.base_reg->no << 14) |
1445 ((addr.base_reg->unit & SHORT_UNIT_MASK) << 5));
1447 insn->bits |= (rmask & RMASK_MASK) << 7;
1449 insn->len = 4;
1450 return l;
1453 /* Parse a list of registers for MMOV pipeline prime. */
1454 static const char *
1455 parse_mmov_prime_list (const char *line, const metag_reg **regs,
1456 unsigned int *rmask)
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;
1463 l = parse_gp_regs_list (l, regs, 1, &regs_read);
1465 /* First register must be a port. */
1466 if (l == NULL || regs[0]->unit != UNIT_RD)
1467 return NULL;
1469 l = skip_comma (l);
1471 if (l == NULL)
1472 return NULL;
1474 l = parse_gp_regs_list (l, ra_regs, MMOV_MAX_REGS, &regs_read);
1476 if (l == NULL)
1477 return NULL;
1479 /* Check remaining registers match the first.
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++)
1486 if (ra_regs[i]->unit != UNIT_RD ||
1487 (ra_regs[i]->no != 0x10 && ra_regs[i]->no != regs[0]->no))
1488 return NULL;
1490 mask = (mask << 1) | 0x1;
1493 *rmask = mask;
1495 return l;
1498 /* Parse a MMOV instruction. */
1499 static const char *
1500 parse_mmov (const char *line, metag_insn *insn,
1501 const insn_template *template)
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;
1509 if (is_prime)
1511 const metag_reg *reg;
1512 metag_addr addr;
1514 memset (&addr, 0, sizeof(addr));
1516 l = parse_mmov_prime_list (l, &reg, &rmask);
1518 if (l == NULL)
1519 return NULL;
1521 l = skip_comma (l);
1523 if (l == NULL)
1524 return NULL;
1526 l = parse_mget_mset_addr (l, &addr);
1528 if (l == NULL)
1530 as_bad (_("invalid memory operand"));
1531 return NULL;
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));
1540 else
1542 const metag_reg *regs[MMOV_MAX_REGS + 1];
1543 unsigned int lowest_reg = 0xffffffff;
1544 size_t regs_read = 0;
1546 l = parse_gp_regs_list (l, regs, MMOV_MAX_REGS + 1, &regs_read);
1548 if (l == NULL || regs_read == 0)
1549 return NULL;
1551 if (!is_short_unit (regs[0]->unit) &&
1552 !(is_fpu && regs[0]->unit == UNIT_FX))
1554 return NULL;
1557 if (!(regs[regs_read-1]->unit == UNIT_RD &&
1558 regs[regs_read-1]->no == 0))
1560 return NULL;
1563 if (!check_rmask (regs, regs_read - 1, is_fpu, is_64bit, &lowest_reg,
1564 &rmask))
1565 return NULL;
1567 if (is_fpu)
1569 insn->bits = (template->meta_opcode |
1570 (regs[0]->no << 14) |
1571 ((rmask & RMASK_MASK) << 7));
1573 else
1575 insn->bits = (template->meta_opcode |
1576 (regs[0]->no << 19) |
1577 ((rmask & RMASK_MASK) << 7) |
1578 ((regs[0]->unit & SHORT_UNIT_MASK) << 3));
1582 insn->len = 4;
1583 return l;
1586 /* Parse an immediate constant. */
1587 static const char *
1588 parse_imm_constant (const char *line, metag_insn *insn, int *value)
1590 const char *l = line;
1591 char *save_input_line_pointer;
1592 expressionS *exp = &insn->reloc_exp;
1594 /* Skip #. */
1595 if (*l == '#')
1596 l++;
1597 else
1598 return NULL;
1600 save_input_line_pointer = input_line_pointer;
1601 input_line_pointer = (char *) l;
1603 expression (exp);
1605 l = input_line_pointer;
1606 input_line_pointer = save_input_line_pointer;
1608 if (exp->X_op == O_constant)
1610 *value = exp->X_add_number;
1612 return l;
1614 else
1616 return NULL;
1620 /* Parse an MDRD instruction. */
1621 static const char *
1622 parse_mdrd (const char *line, metag_insn *insn,
1623 const insn_template *template)
1625 const char *l = line;
1626 unsigned int rmask = 0;
1627 int value = 0, i;
1629 l = parse_imm_constant (l, insn, &value);
1631 if (l == NULL)
1632 return NULL;
1634 if (value < 1 || value > 8)
1636 as_bad (_("MDRD value must be between 1 and 8"));
1637 return NULL;
1640 for (i = 1; i < value; i++)
1642 rmask <<= 1;
1643 rmask |= 1;
1646 insn->bits = (template->meta_opcode |
1647 (rmask << 7));
1649 insn->len = 4;
1650 return l;
1653 /* Parse a conditional SET instruction. */
1654 static const char *
1655 parse_cond_set (const char *line, metag_insn *insn,
1656 const insn_template *template)
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;
1664 memset(&addr, 0, sizeof(addr));
1665 addr.reloc_type = BFD_RELOC_UNUSED;
1667 l = parse_set (l, regs, &addr, size);
1669 if (l == NULL)
1670 return NULL;
1672 if (regs[0]->unit == UNIT_RD)
1674 if (regs[0]->no != 0)
1676 as_bad (_("set can only use RD port as source"));
1677 return NULL;
1679 reg_no = 16;
1681 else
1682 reg_no = regs[0]->no;
1684 if (addr.update)
1685 return NULL;
1687 if (!(addr.immediate &&
1688 addr.exp.X_add_number == 0))
1689 return NULL;
1691 insn->bits = (template->meta_opcode |
1692 (reg_no << 19) |
1693 (regs[0]->unit << 10));
1695 if (!is_short_unit (addr.base_reg->unit))
1697 as_bad (_("base unit must be one of %s"), SHORT_UNITS);
1698 return NULL;
1701 insn->bits |= ((addr.base_reg->no << 14) |
1702 ((addr.base_reg->unit & SHORT_UNIT_MASK) << 5));
1704 insn->len = 4;
1705 return l;
1708 /* Parse an XFR instruction. */
1709 static const char *
1710 parse_xfr (const char *line, metag_insn *insn,
1711 const insn_template *template)
1713 const char *l = line;
1714 metag_addr dest_addr, src_addr;
1715 unsigned int size = 4;
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;
1722 l = parse_addr (l, &dest_addr, size);
1724 if (l == NULL ||
1725 dest_addr.immediate == 1)
1727 as_bad (_("invalid destination memory operand"));
1728 return NULL;
1731 l = skip_comma (l);
1733 if (l == NULL ||
1734 *l == END_OF_INSN)
1735 return NULL;
1737 l = parse_addr (l, &src_addr, size);
1739 if (l == NULL ||
1740 src_addr.immediate == 1)
1742 as_bad (_("invalid source memory operand"));
1743 return NULL;
1746 if (!is_short_unit (dest_addr.base_reg->unit) ||
1747 !is_short_unit (src_addr.base_reg->unit))
1749 as_bad (_("address units must be one of %s"), SHORT_UNITS);
1750 return NULL;
1753 if ((dest_addr.base_reg->unit != dest_addr.offset_reg->unit) ||
1754 (src_addr.base_reg->unit != src_addr.offset_reg->unit))
1756 as_bad (_("base and offset must be from the same unit"));
1757 return NULL;
1760 if (dest_addr.update == 1 &&
1761 src_addr.update == 1 &&
1762 dest_addr.post_increment != src_addr.post_increment)
1764 as_bad (_("source and destination increment mode must agree"));
1765 return NULL;
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));
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)));
1777 if (dest_addr.update == 1)
1778 insn->bits |= (1 << 26);
1780 if (src_addr.update == 1)
1781 insn->bits |= (1 << 27);
1783 if (dest_addr.post_increment == 1 ||
1784 src_addr.post_increment == 1)
1785 insn->bits |= (1 << 24);
1787 insn->len = 4;
1788 return l;
1791 /* Parse an 8bit immediate value. */
1792 static const char *
1793 parse_imm8 (const char *line, metag_insn *insn, int *value)
1795 const char *l = line;
1796 char *save_input_line_pointer;
1797 expressionS *exp = &insn->reloc_exp;
1799 /* Skip #. */
1800 if (*l == '#')
1801 l++;
1802 else
1803 return NULL;
1805 save_input_line_pointer = input_line_pointer;
1806 input_line_pointer = (char *) l;
1808 expression (exp);
1810 l = input_line_pointer;
1811 input_line_pointer = save_input_line_pointer;
1813 if (exp->X_op == O_absent || exp->X_op == O_big)
1815 return NULL;
1817 else if (exp->X_op == O_constant)
1819 *value = exp->X_add_number;
1821 else
1823 insn->reloc_type = BFD_RELOC_METAG_REL8;
1824 insn->reloc_pcrel = 0;
1827 return l;
1830 /* Parse a 16bit immediate value. */
1831 static const char *
1832 parse_imm16 (const char *line, metag_insn *insn, int *value)
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;
1840 /* Skip #. */
1841 if (*l == '#')
1842 l++;
1843 else
1844 return NULL;
1846 if (strncasecmp (l, "HI", 2) == 0)
1848 is_hi = true;
1849 l += 2;
1851 else if (strncasecmp (l, "LO", 2) == 0)
1853 is_lo = true;
1854 l += 2;
1857 save_input_line_pointer = input_line_pointer;
1858 input_line_pointer = (char *) l;
1860 expression (exp);
1862 l = input_line_pointer;
1863 input_line_pointer = save_input_line_pointer;
1865 if (exp->X_op == O_absent || exp->X_op == O_big)
1867 return NULL;
1869 else if (exp->X_op == O_constant)
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;
1878 else
1880 if (exp->X_op == O_PIC_reloc)
1882 exp->X_op = O_symbol;
1884 if (exp->X_md == BFD_RELOC_METAG_GOTOFF)
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;
1893 else if (exp->X_md == BFD_RELOC_METAG_PLT)
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;
1902 else if (exp->X_md == BFD_RELOC_METAG_TLS_LDO)
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;
1911 else if (exp->X_md == BFD_RELOC_METAG_TLS_IENONPIC)
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;
1920 else if (exp->X_md == BFD_RELOC_METAG_TLS_LE)
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;
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;
1933 else
1935 if (exp->X_op == O_symbol && exp->X_add_symbol == GOT_symbol)
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;
1944 else
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;
1955 insn->reloc_pcrel = 0;
1958 return l;
1961 /* Parse a MOV to control unit instruction. */
1962 static const char *
1963 parse_mov_ct (const char *line, metag_insn *insn,
1964 const insn_template *template)
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;
1973 l = parse_gp_regs (l, regs, 1);
1975 if (l == NULL)
1976 return NULL;
1978 if (is_trace)
1980 if (regs[0]->unit != UNIT_TT)
1981 return NULL;
1983 else
1985 if (regs[0]->unit != UNIT_CT)
1986 return NULL;
1989 l = skip_comma (l);
1991 if (l == NULL ||
1992 *l == END_OF_INSN)
1993 return NULL;
1995 l = parse_imm16 (l, insn, &value);
1997 if (l == NULL)
1998 return NULL;
2000 if (value < 0)
2001 sign_extend = 1;
2003 insn->bits = (template->meta_opcode |
2004 (regs[0]->no << 19) |
2005 ((value & IMM16_MASK) << 3));
2007 if (sign_extend && !top)
2008 insn->bits |= (1 << 1);
2010 insn->len = 4;
2011 return l;
2014 /* Parse a SWAP instruction. */
2015 static const char *
2016 parse_swap (const char *line, metag_insn *insn,
2017 const insn_template *template)
2019 const char *l = line;
2020 const metag_reg *regs[2];
2022 l = parse_gp_regs (l, regs, 2);
2024 if (l == NULL)
2025 return NULL;
2027 /* PC.r | CT.r | TR.r | TT.r are treated as if they are a single unit. */
2028 switch (regs[0]->unit)
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)
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;
2042 break;
2044 default:
2045 /* Registers must be in different units. */
2046 if (regs[0]->unit == regs[1]->unit)
2048 as_bad (_("source and destination register must be in different units"));
2049 return NULL;
2051 break;
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));
2060 insn->len = 4;
2061 return l;
2064 /* Parse a JUMP instruction. */
2065 static const char *
2066 parse_jump (const char *line, metag_insn *insn,
2067 const insn_template *template)
2069 const char *l = line;
2070 const metag_reg *regs[1];
2071 int value = 0;
2073 l = parse_gp_regs (l, regs, 1);
2075 if (l == NULL)
2076 return NULL;
2078 if (!is_short_unit (regs[0]->unit))
2080 as_bad (_("register unit must be one of %s"), SHORT_UNITS);
2081 return false;
2084 l = skip_comma (l);
2086 if (l == NULL ||
2087 *l == END_OF_INSN)
2088 return NULL;
2090 l = parse_imm16 (l, insn, &value);
2092 if (l == NULL)
2093 return NULL;
2095 insn->bits = (template->meta_opcode |
2096 (regs[0]->no << 19) |
2097 (regs[0]->unit & SHORT_UNIT_MASK) |
2098 ((value & IMM16_MASK) << 3));
2100 insn->len = 4;
2101 return l;
2104 /* Parse a 19bit immediate value. */
2105 static const char *
2106 parse_imm19 (const char *line, metag_insn *insn, int *value)
2108 const char *l = line;
2109 char *save_input_line_pointer;
2110 expressionS *exp = &insn->reloc_exp;
2112 /* Skip #. */
2113 if (*l == '#')
2114 l++;
2116 save_input_line_pointer = input_line_pointer;
2117 input_line_pointer = (char *) l;
2119 expression (exp);
2121 l = input_line_pointer;
2122 input_line_pointer = save_input_line_pointer;
2124 if (exp->X_op == O_absent || exp->X_op == O_big)
2126 return NULL;
2128 else if (exp->X_op == O_constant)
2130 *value = exp->X_add_number;
2132 else
2134 if (exp->X_op == O_PIC_reloc)
2136 exp->X_op = O_symbol;
2138 if (exp->X_md == BFD_RELOC_METAG_PLT)
2139 insn->reloc_type = BFD_RELOC_METAG_RELBRANCH_PLT;
2140 else
2141 return NULL;
2143 else
2144 insn->reloc_type = BFD_RELOC_METAG_RELBRANCH;
2145 insn->reloc_pcrel = 1;
2148 return l;
2151 /* Parse a CALLR instruction. */
2152 static const char *
2153 parse_callr (const char *line, metag_insn *insn,
2154 const insn_template *template)
2156 const char *l = line;
2157 const metag_reg *regs[1];
2158 int value = 0;
2160 l = parse_gp_regs (l, regs, 1);
2162 if (l == NULL)
2163 return NULL;
2165 if (!is_short_unit (regs[0]->unit))
2167 as_bad (_("link register unit must be one of %s"), SHORT_UNITS);
2168 return NULL;
2171 if (regs[0]->no & ~CALLR_REG_MASK)
2173 as_bad (_("link register must be in a low numbered register"));
2174 return NULL;
2177 l = skip_comma (l);
2179 if (l == NULL ||
2180 *l == END_OF_INSN)
2181 return NULL;
2183 l = parse_imm19 (l, insn, &value);
2185 if (l == NULL)
2186 return NULL;
2188 if (!within_signed_range (value / 4, IMM19_BITS))
2190 as_bad (_("target out of range"));
2191 return NULL;
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));
2199 insn->len = 4;
2200 return l;
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
2207 lookup_o2r (unsigned int is_addr, unsigned int unit_bit, const metag_reg *reg)
2209 if (reg->no & ~O2R_REG_MASK)
2210 return -1;
2212 if (is_addr)
2214 if (unit_bit)
2216 switch (reg->unit)
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;
2230 else
2232 switch (reg->unit)
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;
2247 else
2249 if (unit_bit)
2251 switch (reg->unit)
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;
2265 else
2267 switch (reg->unit)
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;
2284 /* Parse GP ALU instruction. */
2285 static const char *
2286 parse_alu (const char *line, metag_insn *insn,
2287 const insn_template *template)
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;
2304 l = parse_gp_regs (l, dest_regs, 1);
2306 if (l == NULL)
2307 return NULL;
2309 l = skip_comma (l);
2311 if (l == NULL ||
2312 *l == END_OF_INSN)
2313 return NULL;
2315 if (is_addr_op)
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;
2322 else
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;
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;
2336 if (imm)
2338 if (!cond)
2340 if (is_addr_op)
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;
2349 else
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;
2360 if (cond)
2362 l = parse_gp_regs (l, src_regs, 1);
2364 if (l == NULL)
2365 return NULL;
2367 l = skip_comma (l);
2369 if (l == NULL ||
2370 *l == END_OF_INSN)
2371 return NULL;
2373 if (is_addr_op)
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;
2382 else
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;
2392 if (src_regs[0]->unit != dest_regs[0]->unit && !ca)
2393 return NULL;
2395 l = parse_imm8 (l, insn, &value);
2397 if (l == NULL)
2398 return NULL;
2400 if (!within_unsigned_range (value, IMM8_BITS))
2401 return NULL;
2403 insn->bits = (template->meta_opcode |
2404 (dest_regs[0]->no << 19) |
2405 (src_regs[0]->no << 14) |
2406 ((value & IMM8_MASK) << 6));
2408 if (ca)
2410 if (is_addr_op)
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;
2419 else
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;
2429 insn->bits |= dest_regs[0]->unit << 1;
2432 else if (o1z)
2434 l = parse_imm16 (l, insn, &value);
2436 if (l == NULL)
2437 return NULL;
2439 if (value < 0)
2441 if (!within_signed_range (value, IMM16_BITS))
2443 as_bad (_("immediate out of range"));
2444 return NULL;
2446 sign_extend = 1;
2448 else
2450 if (!within_unsigned_range (value, IMM16_BITS))
2452 as_bad (_("immediate out of range"));
2453 return NULL;
2457 insn->bits = (template->meta_opcode |
2458 (dest_regs[0]->no << 19) |
2459 ((value & IMM16_MASK) << 3));
2461 else
2463 l = parse_gp_regs (l, src_regs, 1);
2465 if (l == NULL)
2466 return NULL;
2468 if (!(src_regs[0]->unit == dest_regs[0]->unit))
2469 return NULL;
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;
2476 l = skip_comma (l);
2478 if (l == NULL ||
2479 *l == END_OF_INSN)
2480 return NULL;
2482 l = parse_imm16 (l, insn, &value);
2484 if (l == NULL)
2485 return NULL;
2487 if (value < 0)
2489 if (!within_signed_range (value, IMM16_BITS))
2491 as_bad (_("immediate out of range"));
2492 return NULL;
2494 sign_extend = 1;
2496 else
2498 if (!within_unsigned_range (value, IMM16_BITS))
2500 as_bad (_("immediate out of range"));
2501 return NULL;
2505 insn->bits = (template->meta_opcode |
2506 (dest_regs[0]->no << 19) |
2507 (src_regs[0]->no << 19) |
2508 ((value & IMM16_MASK) << 3));
2511 else
2513 bool o2r = 0;
2514 int rs2;
2516 if (cond || !o1z)
2517 l = parse_gp_regs (l, src_regs, 2);
2518 else
2519 l = parse_gp_regs (l, src_regs, 1);
2521 if (l == NULL)
2522 return NULL;
2524 if (cond || !o1z)
2526 if (is_addr_op)
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;
2535 else
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;
2545 else
2547 if (is_addr_op)
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;
2556 else
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;
2567 if (cond)
2569 if (src_regs[0]->unit != src_regs[1]->unit)
2571 rs2 = lookup_o2r (is_addr_op, unit_bit, src_regs[1]);
2573 if (rs2 < 0)
2574 return NULL;
2576 o2r = 1;
2578 else
2580 rs2 = src_regs[1]->no;
2583 insn->bits = (template->meta_opcode |
2584 (dest_regs[0]->no << 19) |
2585 (src_regs[0]->no << 14) |
2586 (rs2 << 9));
2588 if (is_mul)
2590 if (dest_regs[0]->unit != src_regs[0]->unit && is_mul)
2592 if (ca)
2594 insn->bits |= dest_regs[0]->unit << 1;
2596 else
2597 return NULL;
2600 else
2601 insn->bits |= dest_regs[0]->unit << 5;
2603 else if (o1z)
2605 if (dest_regs[0]->unit != src_regs[0]->unit)
2607 rs2 = lookup_o2r (is_addr_op, unit_bit, src_regs[0]);
2609 if (rs2 < 0)
2610 return NULL;
2612 o2r = 1;
2614 else
2616 rs2 = src_regs[0]->no;
2619 insn->bits = (template->meta_opcode |
2620 (dest_regs[0]->no << 19) |
2621 (rs2 << 9));
2623 else
2625 if (dest_regs[0]->unit != src_regs[0]->unit)
2626 return NULL;
2628 if (dest_regs[0]->unit != src_regs[1]->unit)
2630 rs2 = lookup_o2r (is_addr_op, unit_bit, src_regs[1]);
2632 if (rs2 < 0)
2633 return NULL;
2635 o2r = 1;
2637 else
2639 rs2 = src_regs[1]->no;
2642 insn->bits = (template->meta_opcode |
2643 (dest_regs[0]->no << 19) |
2644 (src_regs[0]->no << 14) |
2645 (rs2 << 9));
2648 if (o2r)
2649 insn->bits |= 1;
2652 if (is_quickrot)
2654 const metag_reg *qr_regs[1];
2655 bool limit_regs = imm && cond;
2657 l = skip_comma (l);
2659 if (l == NULL ||
2660 *l == END_OF_INSN)
2661 return NULL;
2663 l = parse_gp_regs (l, qr_regs, 1);
2665 if (l == NULL)
2666 return NULL;
2668 if (!((unit_bit == 0 && qr_regs[0]->unit != UNIT_A0) ||
2669 !(unit_bit == 1 && qr_regs[0]->unit != UNIT_A1)))
2671 as_bad (_("invalid quickrot unit specified"));
2672 return NULL;
2675 switch (qr_regs[0]->no)
2677 case 2:
2678 break;
2679 case 3:
2680 if (!limit_regs)
2682 insn->bits |= (1 << 7);
2683 break;
2685 /* Fall through. */
2686 default:
2687 as_bad (_("invalid quickrot register specified"));
2688 return NULL;
2692 if (sign_extend && !top)
2693 insn->bits |= (1 << 1);
2695 insn->bits |= unit_bit << 24;
2696 insn->len = 4;
2697 return l;
2700 /* Parse a B instruction. */
2701 static const char *
2702 parse_branch (const char *line, metag_insn *insn,
2703 const insn_template *template)
2705 const char *l = line;
2706 int value = 0;
2708 l = parse_imm19 (l, insn, &value);
2710 if (l == NULL)
2711 return NULL;
2713 if (!within_signed_range (value / 4, IMM19_BITS))
2715 as_bad (_("target out of range"));
2716 return NULL;
2719 insn->bits = (template->meta_opcode |
2720 ((value & IMM19_MASK) << 5));
2722 insn->len = 4;
2723 return l;
2726 /* Parse a KICK instruction. */
2727 static const char *
2728 parse_kick (const char *line, metag_insn *insn,
2729 const insn_template *template)
2731 const char *l = line;
2732 const metag_reg *regs[2];
2734 l = parse_gp_regs (l, regs, 2);
2736 if (l == NULL)
2737 return NULL;
2739 if (regs[1]->unit != UNIT_TR)
2741 as_bad (_("source register must be in the trigger unit"));
2742 return NULL;
2745 insn->bits = (template->meta_opcode |
2746 (regs[1]->no << 19) |
2747 (regs[0]->no << 14) |
2748 (regs[0]->unit << 5));
2750 insn->len = 4;
2751 return l;
2754 /* Parse a SWITCH instruction. */
2755 static const char *
2756 parse_switch (const char *line, metag_insn *insn,
2757 const insn_template *template)
2759 const char *l = line;
2760 int value = 0;
2762 l = parse_imm_constant (l, insn, &value);
2764 if (l == NULL)
2765 return NULL;
2767 if (!within_unsigned_range (value, IMM24_BITS))
2769 as_bad (_("target out of range"));
2770 return NULL;
2773 insn->bits = (template->meta_opcode |
2774 (value & IMM24_MASK));
2776 insn->len = 4;
2777 return l;
2780 /* Parse a shift instruction. */
2781 static const char *
2782 parse_shift (const char *line, metag_insn *insn,
2783 const insn_template *template)
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;
2793 l = parse_gp_regs (l, regs, 2);
2795 if (l == NULL)
2796 return NULL;
2798 l = skip_comma (l);
2800 if (l == NULL ||
2801 *l == END_OF_INSN)
2802 return NULL;
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;
2811 if (regs[0]->unit != regs[1]->unit && !(cond && ca))
2812 return NULL;
2814 if (*l == '#')
2816 l = parse_imm_constant (l, insn, &value);
2818 if (l == NULL)
2819 return NULL;
2821 if (!within_unsigned_range (value, IMM5_BITS))
2822 return NULL;
2824 insn->bits = (template->meta_opcode |
2825 (1 << 25) |
2826 (regs[0]->no << 19) |
2827 (regs[1]->no << 14) |
2828 ((value & IMM5_MASK) << 9));
2830 else
2832 l = parse_gp_regs (l, src2_regs, 1);
2834 if (l == NULL)
2835 return NULL;
2837 insn->bits = (template->meta_opcode |
2838 (regs[0]->no << 19) |
2839 (regs[1]->no << 14) |
2840 (src2_regs[0]->no << 9));
2842 if (src2_regs[0]->unit != regs[1]->unit)
2844 as_bad(_("Source registers must be in the same unit"));
2845 return NULL;
2849 if (regs[0]->unit != regs[1]->unit)
2851 if (cond && ca)
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;
2860 insn->bits |= ((1 << 5) |
2861 (regs[0]->unit << 1));
2863 else
2864 return NULL;
2867 insn->bits |= unit_bit << 24;
2868 insn->len = 4;
2869 return l;
2872 /* Parse a MIN or MAX instruction. */
2873 static const char *
2874 parse_min_max (const char *line, metag_insn *insn,
2875 const insn_template *template)
2877 const char *l = line;
2878 const metag_reg *regs[3];
2880 l = parse_gp_regs (l, regs, 3);
2882 if (l == NULL)
2883 return NULL;
2885 if (!(regs[0]->unit == UNIT_D0 ||
2886 regs[0]->unit == UNIT_D1))
2887 return NULL;
2889 if (!(regs[0]->unit == regs[1]->unit &&
2890 regs[1]->unit == regs[2]->unit))
2891 return NULL;
2893 insn->bits = (template->meta_opcode |
2894 (regs[0]->no << 19) |
2895 (regs[1]->no << 14) |
2896 (regs[2]->no << 9));
2898 if (regs[0]->unit == UNIT_D1)
2899 insn->bits |= (1 << 24);
2901 insn->len = 4;
2902 return l;
2905 /* Parse a bit operation instruction. */
2906 static const char *
2907 parse_bitop (const char *line, metag_insn *insn,
2908 const insn_template *template)
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;
2915 if (swap_inst && ((template->meta_opcode >> 1) & 0xb) == 0xa)
2916 is_bexl = 1;
2918 l = parse_gp_regs (l, regs, 2);
2920 if (l == NULL)
2921 return NULL;
2923 if (!(regs[0]->unit == UNIT_D0 ||
2924 regs[0]->unit == UNIT_D1))
2925 return NULL;
2927 if (is_bexl)
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;
2936 else if (!(regs[0]->unit == regs[1]->unit))
2937 return NULL;
2939 insn->bits = (template->meta_opcode |
2940 (regs[0]->no << 19) |
2941 (regs[1]->no << 14));
2943 if (swap_inst)
2945 if (regs[1]->unit == UNIT_D1)
2946 insn->bits |= 1;
2948 else
2950 if (regs[1]->unit == UNIT_D1)
2951 insn->bits |= (1 << 24);
2954 insn->len = 4;
2955 return l;
2958 /* Parse a CMP or TST instruction. */
2959 static const char *
2960 parse_cmp (const char *line, metag_insn *insn,
2961 const insn_template *template)
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;
2973 l = parse_gp_regs (l, dest_regs, 1);
2975 if (l == NULL)
2976 return NULL;
2978 l = skip_comma (l);
2980 if (l == NULL ||
2981 *l == END_OF_INSN)
2982 return NULL;
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;
2991 if (imm)
2993 if (cond)
2995 l = parse_imm_constant (l, insn, &value);
2997 if (l == NULL)
2998 return NULL;
3000 if (!within_unsigned_range (value, IMM8_BITS))
3001 return NULL;
3003 insn->bits = (template->meta_opcode |
3004 (dest_regs[0]->no << 14) |
3005 ((value & IMM8_MASK) << 6));
3008 else
3010 l = parse_imm16 (l, insn, &value);
3012 if (l == NULL)
3013 return NULL;
3015 if (value < 0)
3017 if (!within_signed_range (value, IMM16_BITS))
3019 as_bad (_("immediate out of range"));
3020 return NULL;
3022 sign_extend = 1;
3024 else
3026 if (!within_unsigned_range (value, IMM16_BITS))
3028 as_bad (_("immediate out of range"));
3029 return NULL;
3033 insn->bits = (template->meta_opcode |
3034 (dest_regs[0]->no << 19) |
3035 ((value & IMM16_MASK) << 3));
3038 else
3040 bool o2r = 0;
3041 int rs2;
3043 l = parse_gp_regs (l, src_regs, 1);
3045 if (l == NULL)
3046 return NULL;
3048 if (dest_regs[0]->unit != src_regs[0]->unit)
3050 rs2 = lookup_o2r (0, unit_bit, src_regs[0]);
3052 if (rs2 < 0)
3053 return NULL;
3055 o2r = 1;
3057 else
3059 rs2 = src_regs[0]->no;
3062 insn->bits = (template->meta_opcode |
3063 (dest_regs[0]->no << 14) |
3064 (rs2 << 9));
3066 if (o2r)
3067 insn->bits |= 1;
3070 if (sign_extend && !top)
3071 insn->bits |= (1 << 1);
3073 insn->bits |= unit_bit << 24;
3074 insn->len = 4;
3075 return l;
3078 /* Parse a CACHEW instruction. */
3079 static const char *
3080 parse_cachew (const char *line, metag_insn *insn,
3081 const insn_template *template)
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;
3089 memset(&addr, 0, sizeof(addr));
3090 addr.reloc_type = BFD_RELOC_UNUSED;
3092 l = parse_addr (l, &addr, size);
3094 if (l == NULL ||
3095 !is_short_unit (addr.base_reg->unit) ||
3096 addr.update ||
3097 !addr.immediate)
3099 as_bad (_("invalid memory operand"));
3100 return NULL;
3103 l = skip_comma (l);
3105 if (l == NULL ||
3106 *l == END_OF_INSN)
3107 return NULL;
3109 if (size == 4)
3110 l = parse_gp_regs (l, src_regs, 1);
3111 else
3112 l = parse_pair_gp_regs (l, src_regs);
3114 if (l == NULL ||
3115 !is_short_unit (src_regs[0]->unit))
3117 as_bad (_("invalid source register"));
3118 return NULL;
3121 offset = addr.exp.X_add_number;
3123 if (addr.negate)
3124 offset = -offset;
3126 offset = offset / 64;
3128 if (!within_signed_range (offset, GET_SET_IMM_BITS))
3130 as_bad (_("offset value out of range"));
3131 return NULL;
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));
3141 insn->len = 4;
3142 return l;
3145 /* Parse a CACHEW instruction. */
3146 static const char *
3147 parse_cacher (const char *line, metag_insn *insn,
3148 const insn_template *template)
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;
3156 memset(&addr, 0, sizeof(addr));
3157 addr.reloc_type = BFD_RELOC_UNUSED;
3159 if (size == 4)
3160 l = parse_gp_regs (l, dest_regs, 1);
3161 else
3162 l = parse_pair_gp_regs (l, dest_regs);
3164 if (l == NULL ||
3165 !is_short_unit (dest_regs[0]->unit))
3167 as_bad (_("invalid destination register"));
3168 return NULL;
3171 l = skip_comma (l);
3173 if (l == NULL ||
3174 *l == END_OF_INSN)
3175 return NULL;
3177 l = parse_addr (l, &addr, size);
3179 if (l == NULL ||
3180 !is_short_unit (addr.base_reg->unit) ||
3181 addr.update ||
3182 !addr.immediate)
3184 as_bad (_("invalid memory operand"));
3185 return NULL;
3188 offset = addr.exp.X_add_number;
3190 if (addr.negate)
3191 offset = -offset;
3193 offset = offset / (int)size;
3195 if (!within_signed_range (offset, GET_SET_IMM_BITS))
3197 as_bad (_("offset value out of range"));
3198 return NULL;
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));
3208 insn->len = 4;
3209 return l;
3212 /* Parse an ICACHE instruction. */
3213 static const char *
3214 parse_icache (const char *line, metag_insn *insn,
3215 const insn_template *template)
3217 const char *l = line;
3218 int offset;
3219 int pfcount;
3221 l = parse_imm_constant (l, insn, &offset);
3223 if (l == NULL)
3224 return NULL;
3226 if (!within_signed_range (offset, IMM15_BITS))
3227 return NULL;
3229 l = skip_comma (l);
3231 l = parse_imm_constant (l, insn, &pfcount);
3233 if (l == NULL)
3234 return NULL;
3236 if (!within_unsigned_range (pfcount, IMM4_BITS))
3237 return NULL;
3239 insn->bits = (template->meta_opcode |
3240 ((offset & IMM15_MASK) << 9) |
3241 ((pfcount & IMM4_MASK) << 1));
3243 insn->len = 4;
3244 return l;
3247 /* Parse a LNKGET instruction. */
3248 static const char *
3249 parse_lnkget (const char *line, metag_insn *insn,
3250 const insn_template *template)
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;
3258 memset(&addr, 0, sizeof(addr));
3259 addr.reloc_type = BFD_RELOC_UNUSED;
3261 if (size == 8)
3262 l = parse_pair_gp_regs (l, dest_regs);
3263 else
3264 l = parse_gp_regs (l, dest_regs, 1);
3266 if (l == NULL ||
3267 !is_short_unit (dest_regs[0]->unit))
3269 as_bad (_("invalid destination register"));
3270 return NULL;
3273 l = skip_comma (l);
3275 if (l == NULL ||
3276 *l == END_OF_INSN)
3277 return NULL;
3279 l = parse_addr (l, &addr, size);
3281 if (l == NULL ||
3282 !is_short_unit (addr.base_reg->unit) ||
3283 addr.update ||
3284 !addr.immediate)
3286 as_bad (_("invalid memory operand"));
3287 return NULL;
3290 offset = addr.exp.X_add_number;
3292 if (addr.negate)
3293 offset = -offset;
3295 offset = offset / size;
3297 if (!within_signed_range (offset, GET_SET_IMM_BITS))
3299 as_bad (_("offset value out of range"));
3300 return NULL;
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));
3310 insn->len = 4;
3311 return l;
3314 /* Parse an FPU MOV instruction. */
3315 static const char *
3316 parse_fmov (const char *line, metag_insn *insn,
3317 const insn_template *template)
3319 const char *l = line;
3320 const metag_reg *regs[2];
3322 l = parse_fpu_regs (l, regs, 2);
3324 if (l == NULL)
3325 return NULL;
3327 insn->bits = (template->meta_opcode |
3328 (regs[0]->no << 19) |
3329 (regs[1]->no << 14));
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);
3336 insn->len = 4;
3337 return l;
3340 /* Parse an FPU MMOV instruction. */
3341 static const char *
3342 parse_fmmov (const char *line, metag_insn *insn,
3343 const insn_template *template)
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;
3356 if (insn->fpu_width != FPU_WIDTH_SINGLE)
3357 return NULL;
3359 l = parse_gp_regs_list (l, regs, 16, &regs_read);
3361 if (l == NULL)
3362 return NULL;
3364 if (regs_read % 2)
3365 return NULL;
3367 if (to_fpu)
3369 for (i = 0; i < regs_read / 2; i++)
3371 if (regs[i]->unit != UNIT_FX)
3372 return NULL;
3374 if (last_reg == -1)
3376 last_reg = regs[i]->no;
3377 lowest_fpu_reg = last_reg;
3379 else
3381 if (is_mmovl)
3383 if (regs[i]->no != (unsigned int)(last_reg + 2))
3384 return NULL;
3386 else if (regs[i]->no != (unsigned int)(last_reg + 1))
3387 return NULL;
3389 last_reg = regs[i]->no;
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;
3400 if (!check_rmask (&regs[i], regs_read / 2, true, false, &lowest_data_reg,
3401 &rmask))
3402 return NULL;
3404 else
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;
3413 if (!check_rmask (regs, regs_read / 2, true, false, &lowest_data_reg,
3414 &rmask))
3415 return NULL;
3417 for (i = regs_read / 2; i < regs_read; i++)
3419 if (regs[i]->unit != UNIT_FX)
3420 return NULL;
3422 if (last_reg == -1)
3424 last_reg = regs[i]->no;
3425 lowest_fpu_reg = last_reg;
3427 else
3429 if (is_mmovl)
3431 if (regs[i]->no != (unsigned int)(last_reg + 2))
3432 return NULL;
3434 else if (regs[i]->no != (unsigned int)(last_reg + 1))
3435 return NULL;
3437 last_reg = regs[i]->no;
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);
3448 insn->len = 4;
3449 return l;
3452 /* Parse an FPU data unit MOV instruction. */
3453 static const char *
3454 parse_fmov_data (const char *line, metag_insn *insn,
3455 const insn_template *template)
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;
3462 if (insn->fpu_width == FPU_WIDTH_PAIR)
3463 return NULL;
3465 l = parse_gp_regs (l, regs, 2);
3467 if (l == NULL)
3468 return NULL;
3470 if (to_fpu)
3472 if (regs[0]->unit != UNIT_FX)
3473 return NULL;
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;
3482 else
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;
3491 if (regs[1]->unit != UNIT_FX)
3492 return NULL;
3495 insn->bits = (template->meta_opcode |
3496 (base_unit << 24) |
3497 (regs[0]->no << 19) |
3498 (regs[1]->no << 9));
3500 insn->len = 4;
3501 return l;
3504 /* Parse an FPU immediate MOV instruction. */
3505 static const char *
3506 parse_fmov_i (const char *line, metag_insn *insn,
3507 const insn_template *template)
3509 const char *l = line;
3510 const metag_reg *regs[1];
3511 int value = 0;
3513 l = parse_fpu_regs (l, regs, 1);
3515 l = skip_comma (l);
3517 if (l == NULL ||
3518 *l == END_OF_INSN)
3519 return NULL;
3521 l = parse_imm16 (l, insn, &value);
3523 if (l == NULL)
3524 return NULL;
3526 insn->bits = (template->meta_opcode |
3527 (regs[0]->no << 19) |
3528 ((value & IMM16_MASK) << 3));
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);
3535 insn->len = 4;
3536 return l;
3539 /* Parse an FPU PACK instruction. */
3540 static const char *
3541 parse_fpack (const char *line, metag_insn *insn,
3542 const insn_template *template)
3544 const char *l = line;
3545 const metag_reg *regs[3];
3547 l = parse_fpu_regs (l, regs, 3);
3549 if (l == NULL)
3550 return NULL;
3552 if (regs[0]->no % 2)
3554 as_bad (_("destination register should be even numbered"));
3555 return NULL;
3558 insn->bits = (template->meta_opcode |
3559 (regs[0]->no << 19) |
3560 (regs[1]->no << 14) |
3561 (regs[2]->no << 9));
3563 insn->len = 4;
3564 return l;
3567 /* Parse an FPU SWAP instruction. */
3568 static const char *
3569 parse_fswap (const char *line, metag_insn *insn,
3570 const insn_template *template)
3572 const char *l = line;
3573 const metag_reg *regs[2];
3575 if (insn->fpu_width != FPU_WIDTH_PAIR)
3576 return NULL;
3578 l = parse_fpu_regs (l, regs, 2);
3580 if (l == NULL)
3581 return NULL;
3583 if (regs[0]->no % 2)
3584 return NULL;
3586 if (regs[1]->no % 2)
3587 return NULL;
3589 insn->bits = (template->meta_opcode |
3590 (regs[0]->no << 19) |
3591 (regs[1]->no << 14));
3593 insn->len = 4;
3594 return l;
3597 /* Parse an FPU CMP instruction. */
3598 static const char *
3599 parse_fcmp (const char *line, metag_insn *insn,
3600 const insn_template *template)
3602 const char *l = line, *l2;
3603 const metag_reg *regs1[1];
3604 const metag_reg *regs2[1];
3606 l = parse_fpu_regs (l, regs1, 1);
3608 l = skip_comma (l);
3610 if (l == NULL ||
3611 *l == END_OF_INSN)
3612 return NULL;
3614 l2 = parse_fpu_regs (l, regs2, 1);
3616 if (l2 != NULL)
3618 insn->bits = (regs2[0]->no << 9);
3620 else
3622 int constant = 0;
3623 l2 = parse_imm_constant (l, insn, &constant);
3624 if (!l2 || constant != 0)
3626 as_bad (_("comparison must be with register or #0"));
3627 return NULL;
3629 insn->bits = (1 << 8);
3632 insn->bits |= (template->meta_opcode |
3633 (regs1[0]->no << 14));
3635 if (insn->fpu_action_flags & FPU_ACTION_ABS)
3636 insn->bits |= (1 << 19);
3638 if (insn->fpu_action_flags & FPU_ACTION_QUIET)
3639 insn->bits |= (1 << 7);
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);
3646 insn->len = 4;
3647 return l2;
3650 /* Parse an FPU MIN or MAX instruction. */
3651 static const char *
3652 parse_fminmax (const char *line, metag_insn *insn,
3653 const insn_template *template)
3655 const char *l = line;
3656 const metag_reg *regs[3];
3658 l = parse_fpu_regs (l, regs, 3);
3660 if (l == NULL)
3661 return NULL;
3663 insn->bits = (template->meta_opcode |
3664 (regs[0]->no << 19) |
3665 (regs[1]->no << 14) |
3666 (regs[2]->no << 9));
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);
3673 insn->len = 4;
3674 return l;
3677 /* Parse an FPU data conversion instruction. */
3678 static const char *
3679 parse_fconv (const char *line, metag_insn *insn,
3680 const insn_template *template)
3682 const char *l = line;
3683 const metag_reg *regs[2];
3685 if (insn->fpu_width == FPU_WIDTH_PAIR)
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))
3692 as_bad (_("instruction cannot operate on pair values"));
3693 return NULL;
3697 if (insn->fpu_action_flags & FPU_ACTION_ZERO)
3699 if (strncasecmp (template->name, "FTOI", 4) &&
3700 strncasecmp (template->name, "DTOI", 4) &&
3701 strncasecmp (template->name, "DTOL", 4))
3703 as_bad (_("zero flag is not valid for this instruction"));
3704 return NULL;
3708 l = parse_fpu_regs (l, regs, 2);
3710 if (l == NULL)
3711 return NULL;
3713 if (!strncasecmp (template->name, "DTOL", 4) ||
3714 !strncasecmp (template->name, "LTOD", 4))
3716 if (regs[0]->no % 2)
3718 as_bad (_("destination register should be even numbered"));
3719 return NULL;
3722 if (regs[1]->no % 2)
3724 as_bad (_("source register should be even numbered"));
3725 return NULL;
3729 insn->bits = (template->meta_opcode |
3730 (regs[0]->no << 19) |
3731 (regs[1]->no << 14));
3733 if (insn->fpu_width == FPU_WIDTH_PAIR)
3734 insn->bits |= (1 << 6);
3736 if (insn->fpu_action_flags & FPU_ACTION_ZERO)
3737 insn->bits |= (1 << 12);
3739 insn->len = 4;
3740 return l;
3743 /* Parse an FPU extended data conversion instruction. */
3744 static const char *
3745 parse_fconvx (const char *line, metag_insn *insn,
3746 const insn_template *template)
3748 const char *l = line;
3749 const metag_reg *regs[2];
3750 int fraction_bits = 0;
3752 if (insn->fpu_width == FPU_WIDTH_PAIR)
3754 if (strncasecmp (template->name, "FTOX", 4) &&
3755 strncasecmp (template->name, "XTOF", 4))
3757 as_bad (_("instruction cannot operate on pair values"));
3758 return NULL;
3762 l = parse_fpu_regs (l, regs, 2);
3764 l = skip_comma (l);
3766 if (l == NULL ||
3767 *l == END_OF_INSN)
3768 return NULL;
3770 l = parse_imm_constant (l, insn, &fraction_bits);
3772 if (l == NULL)
3773 return NULL;
3775 insn->bits = (template->meta_opcode |
3776 (regs[0]->no << 19) |
3777 (regs[1]->no << 14));
3779 if (strncasecmp (template->name, "DTOXL", 5) &&
3780 strncasecmp (template->name, "XLTOD", 5))
3782 if (!within_unsigned_range (fraction_bits, IMM5_BITS))
3784 as_bad (_("fraction bits value out of range"));
3785 return NULL;
3787 insn->bits |= ((fraction_bits & IMM5_MASK) << 9);
3789 else
3791 if (!within_unsigned_range (fraction_bits, IMM6_BITS))
3793 as_bad (_("fraction bits value out of range"));
3794 return NULL;
3796 insn->bits |= ((fraction_bits & IMM6_MASK) << 8);
3799 if (insn->fpu_width == FPU_WIDTH_PAIR)
3800 insn->bits |= (1 << 6);
3802 insn->len = 4;
3803 return l;
3806 /* Parse an FPU basic arithmetic instruction. */
3807 static const char *
3808 parse_fbarith (const char *line, metag_insn *insn,
3809 const insn_template *template)
3811 const char *l = line;
3812 const metag_reg *regs[3];
3814 l = parse_fpu_regs (l, regs, 3);
3816 if (l == NULL)
3817 return NULL;
3819 insn->bits = (template->meta_opcode |
3820 (regs[0]->no << 19) |
3821 (regs[1]->no << 14) |
3822 (regs[2]->no << 9));
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);
3829 if (insn->fpu_action_flags & FPU_ACTION_INV)
3830 insn->bits |= (1 << 7);
3832 insn->len = 4;
3833 return l;
3836 /* Parse a floating point accumulator name. */
3837 static const char *
3838 parse_acf (const char *line, int *part)
3840 const char *l = line;
3841 size_t i;
3843 for (i = 0; i < sizeof(metag_acftab)/sizeof(metag_acftab[0]); i++)
3845 const metag_acf *acf = &metag_acftab[i];
3846 size_t name_len = strlen (acf->name);
3848 if (strncasecmp (l, acf->name, name_len) == 0)
3850 l += name_len;
3851 *part = acf->part;
3852 return l;
3855 return NULL;
3858 /* Parse an FPU extended arithmetic instruction. */
3859 static const char *
3860 parse_fearith (const char *line, metag_insn *insn,
3861 const insn_template *template)
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;
3871 if (!strncasecmp (template->name, "MAW", 3))
3872 is_maw = 1;
3874 if (!strncasecmp (template->name, "MAC", 3))
3876 int part;
3877 l = parse_acf (l, &part);
3879 if (l == NULL || part != 0)
3880 return NULL;
3882 l = skip_comma (l);
3884 l = parse_fpu_regs (l, &regs[1], 2);
3886 is_mac = 1;
3888 else
3890 if (is_o3o && is_maw)
3891 l = parse_fpu_regs (l, regs, 2);
3892 else
3893 l = parse_fpu_regs (l, regs, 3);
3896 if (l == NULL)
3897 return NULL;
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));
3906 if (!(is_o3o && is_maw))
3907 insn->bits |= (regs[2]->no << 9);
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);
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);
3919 if (!is_mac && !is_maw)
3920 if (insn->fpu_action_flags & FPU_ACTION_INV)
3921 insn->bits |= (1 << 7);
3923 if (is_muz)
3924 if (insn->fpu_action_flags & FPU_ACTION_QUIET)
3925 insn->bits |= (1 << 1);
3927 insn->len = 4;
3928 return l;
3931 /* Parse an FPU RCP or RSQ instruction. */
3932 static const char *
3933 parse_frec (const char *line, metag_insn *insn,
3934 const insn_template *template)
3936 const char *l = line;
3937 const metag_reg *regs[2];
3939 l = parse_fpu_regs (l, regs, 2);
3941 if (l == NULL)
3942 return NULL;
3944 insn->bits = (template->meta_opcode |
3945 (regs[0]->no << 19) |
3946 (regs[1]->no << 14));
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);
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);
3958 if (insn->fpu_action_flags & FPU_ACTION_INV)
3959 insn->bits |= (1 << 7);
3961 insn->len = 4;
3962 return l;
3965 /* Parse an FPU vector arithmetic instruction. */
3966 static const char *
3967 parse_fsimd (const char *line, metag_insn *insn,
3968 const insn_template *template)
3970 const char *l = line;
3971 const metag_reg *regs[3];
3973 if (insn->fpu_width != FPU_WIDTH_PAIR)
3975 as_bad (_("simd instructions operate on pair values (L prefix)"));
3976 return NULL;
3979 l = parse_fpu_regs (l, regs, 3);
3981 if (l == NULL)
3982 return NULL;
3984 if (regs[0]->no % 2)
3986 as_bad (_("destination register should be even numbered"));
3987 return NULL;
3990 if ((regs[1]->no % 2) ||
3991 (regs[2]->no % 2))
3993 as_bad (_("source registers should be even numbered"));
3994 return NULL;
3997 insn->bits = (template->meta_opcode |
3998 (regs[0]->no << 19) |
3999 (regs[1]->no << 14) |
4000 (regs[2]->no << 9));
4002 if (insn->fpu_action_flags & FPU_ACTION_INV)
4003 insn->bits |= (1 << 7);
4005 insn->len = 4;
4006 return l;
4009 /* Parse an FPU accumulator GET or SET instruction. */
4010 static const char *
4011 parse_fget_set_acf (const char *line, metag_insn *insn,
4012 const insn_template *template)
4014 const char *l = line;
4015 int part;
4016 metag_addr addr;
4017 bool is_get = MAJOR_OPCODE (template->meta_opcode) == OPC_GET;
4019 memset(&addr, 0, sizeof(addr));
4020 addr.reloc_type = BFD_RELOC_UNUSED;
4022 if (is_get)
4024 l = parse_acf (l, &part);
4026 l = skip_comma (l);
4028 if (l == NULL)
4029 return NULL;
4031 l = parse_mget_mset_addr (l, &addr);
4033 else
4035 l = parse_mget_mset_addr (l, &addr);
4037 l = skip_comma (l);
4039 if (l == NULL)
4040 return NULL;
4042 l = parse_acf (l, &part);
4045 if (l == NULL)
4046 return NULL;
4048 insn->bits = (template->meta_opcode |
4049 (part << 19));
4051 if (!is_short_unit (addr.base_reg->unit))
4053 as_bad (_("base unit must be one of %s"), SHORT_UNITS);
4054 return NULL;
4057 insn->bits |= ((addr.base_reg->no << 14) |
4058 ((addr.base_reg->unit & SHORT_UNIT_MASK) << 5));
4060 insn->len = 4;
4061 return l;
4064 /* Copy the name of the next register in LINE to REG_BUF. */
4065 static size_t
4066 strip_reg_name(const char *line, char *reg_buf)
4068 const char *l = line;
4069 size_t len = 0;
4071 while (is_register_char (*l))
4073 reg_buf[len] = *l;
4074 l++;
4075 len++;
4076 if (!(len < MAX_REG_LEN))
4077 return 0;
4080 if (len)
4081 reg_buf[len] = '\0';
4083 return len;
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 *
4089 __parse_dsp_reg (const char *line, const metag_reg **reg, htab_t dsp_regtab)
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;
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)
4103 name[len] = *l;
4104 l++;
4105 len++;
4106 if (!(len < MAX_REG_LEN))
4107 return NULL;
4110 if (!len)
4111 return NULL;
4113 name[len] = '\0';
4114 entry.name = name;
4116 _reg = (const metag_reg *) htab_find (dsp_regtab, &entry);
4117 if (!_reg)
4118 return NULL;
4120 *reg = _reg;
4122 return l;
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 *
4128 parse_dsp_insn_reg (const char *line, const metag_reg **reg)
4130 return __parse_dsp_reg (line, reg, dsp_reg_htab);
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.
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 *
4140 parse_dsp_template_reg (const char *line, const metag_reg **reg,
4141 bool load)
4143 return __parse_dsp_reg (line, reg, dsp_tmpl_reg_htab[load]);
4146 /* Parse a single DSP register from LINE. */
4147 static const char *
4148 parse_dsp_reg (const char *line, const metag_reg **reg,
4149 bool tmpl, bool load)
4151 if (tmpl)
4152 return parse_dsp_template_reg (line, reg, load);
4153 else
4154 return parse_dsp_insn_reg (line, reg);
4157 /* Return TRUE if UNIT is an address unit. */
4158 static bool
4159 is_addr_unit (enum metag_unit unit)
4161 switch (unit)
4163 case UNIT_A0:
4164 case UNIT_A1:
4165 return true;
4166 default:
4167 return false;
4171 /* Return TRUE if UNIT1 and UNIT2 are equivalent units. */
4172 static bool
4173 is_same_data_unit (enum metag_unit unit1, enum metag_unit unit2)
4175 if (unit1 == unit2)
4176 return true;
4178 switch (unit1)
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;
4208 return false;
4211 /* Return TRUE if the register NUM is a quickrot control register. */
4212 static bool
4213 is_quickrot_reg (unsigned int num)
4215 switch (num)
4217 case 2:
4218 case 3:
4219 return true;
4222 return false;
4225 /* Return TRUE if REG is an accumulator register. */
4226 static bool
4227 is_accumulator_reg (const metag_reg *reg)
4229 if (reg->unit == UNIT_ACC_D0 || reg->unit == UNIT_ACC_D1)
4230 return true;
4232 return false;
4235 /* Return TRUE if REG is a DSP RAM register. */
4236 static bool
4237 is_dspram_reg (const metag_reg *reg)
4239 if (reg->unit == UNIT_RAM_D0 || reg->unit == UNIT_RAM_D1)
4240 return true;
4242 return false;
4245 static const char *
4246 __parse_gp_reg (const char *line, const metag_reg **reg, bool load)
4248 const char *l = line;
4249 char reg_buf[MAX_REG_LEN];
4250 size_t len = 0;
4252 if (l == NULL)
4253 return NULL;
4255 /* Parse [DSPRAM.x]. */
4256 if (*l == ADDR_BEGIN_CHAR)
4258 l++;
4260 if (l == NULL)
4261 return NULL;
4263 l = parse_dsp_reg (l, reg, true, load);
4264 if (l == NULL)
4265 return NULL;
4267 if (*l == ADDR_END_CHAR)
4268 l++;
4269 else
4271 as_bad (_("expected ']', not %c in %s"), *l, l);
4272 return NULL;
4275 return l;
4277 else
4280 len = strip_reg_name (l, reg_buf);
4281 if (!len)
4282 return NULL;
4284 l += len;
4285 *reg = parse_gp_reg (reg_buf);
4286 if (*reg == NULL)
4287 return NULL;
4290 return l;
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 *
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)
4305 const char *l = line;
4306 int seen_regs = 0;
4307 size_t i;
4308 const metag_reg *reg;
4310 for (i = 0; i < count; i++)
4312 const char *next, *ll;
4314 next = l;
4316 if (i > 0)
4318 l = skip_comma (l);
4319 if (l == NULL)
4321 *regs_read = seen_regs;
4322 return next;
4326 ll = parse_dsp_reg (l, &reg, tmpl, load);
4328 if (!ll)
4330 if (try_gp)
4332 l = __parse_gp_reg (l, &reg, !(first_dst && i == 0));
4333 if (l == NULL)
4335 *regs_read = seen_regs;
4336 return next;
4338 regs[i] = reg;
4339 seen_regs++;
4341 else
4343 *regs_read = seen_regs;
4344 return l;
4347 else
4349 regs[i] = reg;
4350 seen_regs++;
4351 l = ll;
4355 *regs_read = seen_regs;
4356 return l;
4359 /* Parse the following memory references:
4361 - [Ax.r]
4362 - [Ax.r++]
4363 - [Ax.r--]
4364 - [Ax.r+Ax.r++]
4365 - [Ax.r-Ax.r--]
4367 - [DSPRam]
4368 - [DSPRam++]
4369 - [DSPRam+DSPRam++]
4370 - [DSPRam-DSPRam--] */
4371 static const char *
4372 parse_dsp_addr (const char *line, metag_addr *addr, unsigned int size,
4373 bool load)
4375 const char *l = line, *ll;
4376 const metag_reg *regs[1];
4377 size_t regs_read;
4379 /* Skip opening square bracket. */
4380 l++;
4382 l = parse_dsp_regs_list (l, regs, 1, &regs_read, true, true, load, false);
4384 if (l == NULL)
4385 return NULL;
4387 if (!is_addr_unit (regs[0]->unit) &&
4388 !is_dspram_reg (regs[0]))
4390 as_bad (_("invalid register for memory access"));
4391 return NULL;
4394 addr->base_reg = regs[0];
4396 if (*l == ADDR_END_CHAR)
4398 addr->exp.X_op = O_constant;
4399 addr->exp.X_add_symbol = NULL;
4400 addr->exp.X_op_symbol = NULL;
4402 /* Simple register with no offset (0 immediate). */
4403 addr->exp.X_add_number = 0;
4405 addr->immediate = 1;
4406 l++;
4408 return l;
4411 ll = parse_addr_post_incr_op (l, addr);
4413 if (ll && *ll == ADDR_END_CHAR)
4415 if (addr->update == 1)
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;
4424 addr->immediate = 1;
4425 ll++;
4426 return ll;
4429 addr->post_increment = 0;
4431 l = parse_addr_op (l, addr);
4433 if (l == NULL)
4434 return NULL;
4436 l = parse_dsp_regs_list (l, regs, 1, &regs_read, true, true, load, false);
4438 if (l == NULL)
4439 return NULL;
4441 if (regs[0]->unit != addr->base_reg->unit)
4443 as_bad (_("offset and base must be from the same unit"));
4444 return NULL;
4447 addr->offset_reg = regs[0];
4449 if (*l == ADDR_END_CHAR)
4451 l++;
4452 return l;
4455 l = parse_addr_post_incr_op (l, addr);
4457 if (l == NULL)
4458 return NULL;
4460 if (*l == ADDR_END_CHAR)
4462 l++;
4463 return l;
4466 return NULL;
4469 /* Parse a DSP GET or SET instruction. */
4470 static const char *
4471 parse_dget_set (const char *line, metag_insn *insn,
4472 const insn_template *template)
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;
4485 memset(&addr, 0, sizeof(addr));
4486 addr.reloc_type = BFD_RELOC_UNUSED;
4488 size = is_dual ? 8 : 4;
4489 count = is_dual ? 2 : 1;
4491 if (is_get)
4493 /* GETL can be used on one template table entry. */
4494 if (*l == 'T')
4495 count = 1;
4497 l = parse_dsp_regs_list (l, regs, count, &regs_read, false,
4498 false, false, false);
4499 l = skip_comma (l);
4501 if (l == NULL)
4503 as_bad (_("unexpected end of line"));
4504 return NULL;
4507 l = parse_addr (l, &addr, size);
4509 else
4511 l = parse_addr (l, &addr, size);
4513 l = skip_comma (l);
4515 if (l == NULL)
4516 return NULL;
4518 /* GETL can be used on one template table entry. */
4519 if (*l == 'T')
4520 count = 1;
4522 l = parse_dsp_regs_list (l, regs, count, &regs_read, false, false,
4523 false, false);
4526 if (l == NULL)
4527 return NULL;
4529 /* The first register dictates the unit. */
4530 if (regs[0]->unit == UNIT_DT)
4531 is_template = true;
4532 else
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;
4541 rd_reg = regs[0]->no;
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)
4548 if (is_template || !(rd_reg >= 16 && rd_reg < 20))
4550 as_bad (_("'H' modifier only valid for accumulator registers"));
4551 return NULL;
4554 /* Top 8-bits of the accumulator. */
4555 rd_reg |= 8;
4558 if (is_template)
4560 insn->bits = (template->meta_opcode | (1 << 1));
4562 else
4564 insn->bits = (template->meta_opcode | unit);
4567 insn->bits |= (rd_reg << 19);
4569 if (addr.immediate)
4571 int offset = addr.exp.X_add_number;
4573 if (addr.negate)
4574 offset = -offset;
4576 offset = offset / (int)size;
4578 if (!within_signed_range (offset, DGET_SET_IMM_BITS))
4580 as_bad (_("offset value out of range"));
4581 return NULL;
4584 offset = offset & DGET_SET_IMM_MASK;
4586 insn->bits |= (1 << 13);
4587 insn->bits |= (offset << 9);
4589 else
4591 int au = (addr.base_reg->unit == UNIT_A1);
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);
4598 if (is_dual)
4599 insn->bits |= (1 << 2);
4601 if (!is_addr_unit (addr.base_reg->unit))
4603 as_bad (_("base unit must be either A0 or A1"));
4604 return NULL;
4607 unit = (addr.base_reg->unit == UNIT_A0) ? 0 : 1;
4608 insn->bits |= ((addr.base_reg->no << 14) | (unit << 18));
4610 insn->len = 4;
4612 return l;
4615 /* Parse a DSP template instruction. */
4616 static const char *
4617 parse_dtemplate (const char *line, metag_insn *insn,
4618 const insn_template *template)
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;
4627 for (i = 0; i < TEMPLATE_NUM_REGS; i++)
4629 if (l == NULL)
4631 as_bad (_("unexpected end of line"));
4632 return NULL;
4635 /* We may only have 3 register operands. */
4636 if (*l == END_OF_INSN && i == 3)
4638 daop_only = true;
4639 break;
4642 if (i != 0)
4644 l = skip_comma (l);
4645 if (l == NULL)
4646 return NULL;
4649 if (*l == IMM_CHAR)
4651 l = parse_imm_constant (l, insn, &regs_val[i]);
4652 if (l == NULL)
4654 as_bad (_("invalid immediate"));
4655 return NULL;
4657 regs_which[i] = 0;
4659 else
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)
4668 /* Try the store table too. */
4669 l = __parse_gp_reg (l2, &regs[i], false);
4670 if (l == NULL)
4672 /* Then try a DSP register. */
4673 l = parse_dsp_insn_reg (l2, &regs[i]);
4674 if (l == NULL || regs[i]->unit == UNIT_DT)
4676 as_bad (_("invalid register"));
4677 return NULL;
4681 regs_which[i] = 1;
4685 insn->bits = template->meta_opcode;
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);
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);
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);
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);
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. */
4713 insn->len = 4;
4715 return l;
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 *
4722 template_mem_ref(const char *line, metag_addr *addr,
4723 bool *dspram, int size, bool load)
4725 const char *l = line;
4727 l = parse_dsp_addr (l, addr, size, load);
4729 if (l != NULL)
4731 if (is_addr_unit(addr->base_reg->unit))
4732 *dspram = false;
4733 else
4734 *dspram = true;
4737 return l;
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 *
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)
4748 const char *l = line;
4750 if (l == NULL)
4751 return NULL;
4753 /* DSP Template load definition (Tx, [Ax]) */
4754 if (*l == 'T')
4756 *load = true;
4757 l = parse_dsp_reg (l, &template_reg[0], false, false);
4758 if (l == NULL)
4759 return NULL;
4761 l = skip_comma (l);
4763 l = template_mem_ref (l, addr, dspram, size, *load);
4765 if (addr->base_reg->unit == UNIT_A1)
4766 *addr_unit = 1;
4769 else if (*l == ADDR_BEGIN_CHAR) /* DSP Template store ([Ax], Tx) */
4771 *load = false;
4772 l = template_mem_ref (l, addr, dspram, size, *load);
4773 l = skip_comma(l);
4775 if (l == NULL)
4776 return NULL;
4778 l = parse_dsp_reg (l, &template_reg[0], false, false);
4779 if (l == NULL)
4780 return NULL;
4782 if (addr->base_reg->unit == UNIT_A1)
4783 *addr_unit = 1;
4785 else
4787 as_bad (_("invalid register operand"));
4788 return NULL;
4791 return l;
4794 #define INVALID_SHIFT (-1)
4796 static metag_reg _reg;
4798 /* Parse a template instruction definition. */
4799 static const char *
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)
4807 const char *l = line;
4808 metag_addr addr;
4809 const metag_reg *template_reg[1];
4811 memset (&addr, 0, sizeof(addr));
4813 regs_shift[0] = 19;
4814 regs_shift[1] = INVALID_SHIFT;
4816 insn->bits |= (1 << 1);
4818 l = skip_whitespace (l);
4820 l = parse_template_regs (l, load, au, template_reg,
4821 &addr, dspram, size);
4822 if (l == NULL)
4824 as_bad (_("could not parse template definition"));
4825 return NULL;
4828 regs[2] = template_reg[0];
4829 regs_shift[2] = 9;
4831 /* DSPRAM definition. */
4832 if (*dspram)
4835 _reg = *addr.base_reg;
4837 if (addr.immediate)
4839 /* Set the post-increment bit in the register field. */
4840 if (addr.update)
4841 _reg.no |= 0x1;
4843 else
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;
4853 regs[0] = &_reg;
4855 insn->bits |= (0x3 << 17); /* This signifies a DSPRAM definition. */
4857 else /* DaOpPaMe definition. */
4859 regs[0] = addr.base_reg;
4860 if (addr.immediate)
4862 /* Set the I bit. */
4863 insn->bits |= (1 << 18);
4865 if (addr.update == 1)
4867 if (addr.negate == 1)
4868 *imm = 0x3;
4869 else
4870 *imm = 0x1;
4873 *imm_shift = 14;
4874 *imm_mask = 0x3;
4876 else
4878 /* Setup the offset register. */
4879 regs[1] = addr.offset_reg;
4880 regs_shift[1] = 14;
4882 *au_shift = 23;
4885 *ls_shift = 13;
4887 return l;
4890 /* Does this combination of units need the O2R bit and can it be encoded? */
4891 static bool
4892 units_need_o2r (enum metag_unit unit1, enum metag_unit unit2)
4894 if (unit1 == unit2)
4895 return false;
4897 if (unit1 == UNIT_D0 || unit1 == UNIT_ACC_D0 || unit1 == UNIT_RAM_D0)
4899 if (unit2 == UNIT_ACC_D0 || unit2 == UNIT_RAM_D0 || unit2 == UNIT_D0)
4900 return false;
4902 switch (unit2)
4904 case UNIT_A1:
4905 case UNIT_D1:
4906 case UNIT_RD:
4907 case UNIT_A0:
4908 return true;
4909 default:
4910 return false;
4914 if (unit1 == UNIT_D1 || unit1 == UNIT_ACC_D1 || unit1 == UNIT_RAM_D1)
4916 if (unit2 == UNIT_ACC_D1 || unit2 == UNIT_RAM_D1 || unit2 == UNIT_D1)
4917 return false;
4919 switch (unit2)
4921 case UNIT_A1:
4922 case UNIT_D0:
4923 case UNIT_RD:
4924 case UNIT_A0:
4925 return true;
4926 default:
4927 return false;
4931 return false;
4934 /* Return TRUE if this is a DSP data unit. */
4935 static bool
4936 is_dsp_data_unit (const metag_reg *reg)
4938 switch (reg->unit)
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;
4952 static metag_reg o2r_reg;
4954 /* Parse a DaOpPaMe load template definition. */
4955 static const char *
4956 parse_dalu (const char *line, metag_insn *insn,
4957 const insn_template *template)
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;
5008 /* XFIXME: check the flags are valid with the instruction. */
5009 if (is_quickrot64 && !(template->arg_type & DSP_ARGS_QR))
5011 as_bad (_("QUICKRoT 64-bit extension not applicable to this instruction"));
5012 return NULL;
5015 insn->bits = template->meta_opcode;
5017 memset (regs, 0, sizeof (regs));
5018 memset (&addr, 0, sizeof (addr));
5020 /* There are the following forms of DSP ALU instructions,
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
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
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 */
5050 /* Group 1. */
5051 if (template->arg_type & DSP_ARGS_1)
5053 du_shift = 24;
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)
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]))
5064 if (regs[0]->unit != regs[1]->unit ||
5065 regs[2]->unit == regs[1]->unit)
5067 as_bad (_("invalid operands for cross-unit op"));
5068 return NULL;
5071 du = (regs[1]->unit == UNIT_ACC_D1);
5072 regs_shift[1] = 19;
5073 l = ll;
5075 /* All cross-unit accumulator ops have bits 8 and 6 set. */
5076 insn->bits |= (5 << 6);
5078 goto check_for_template;
5081 /* If we reach here, this instruction is not a
5082 cross-unit accumulator op. */
5085 if (template->arg_type & DSP_ARGS_SPLIT8)
5086 om_shift = 7;
5088 sc_shift = 5;
5089 l1_shift = 4;
5090 o2r_shift = 0;
5092 /* De.r|ACe.r,Dx.r,De.r */
5093 if (template->arg_type & DSP_ARGS_DACC)
5095 /* XFIXME: these need moving? */
5096 a2_shift = 7;
5097 su_shift = 6;
5098 a1_shift = 2;
5099 om_shift = 3;
5101 ll = parse_dsp_reg (l, &regs[0], false, false);
5102 if (ll != NULL)
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)))
5109 as_bad (_("missing flags: one of 'P', 'N' or 'Z' required"));
5110 return NULL;
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)
5119 as_bad (_("invalid register"));
5120 return NULL;
5123 if (regs[1]->unit == UNIT_D1 || regs[1]->unit == UNIT_RAM_D1)
5124 du = 1;
5126 regs_shift[0] = 19;
5127 regs_shift[1] = 14;
5128 regs_shift[2] = 9;
5129 goto check_for_template;
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)))
5137 as_bad (_("'P', 'N' or 'Z' flags may only be specified when accumulating"));
5138 return NULL;
5142 regs_shift[0] = 19;
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;
5149 l = skip_comma (l);
5150 if (l == NULL)
5151 return NULL;
5153 if (regs[1]->unit == UNIT_D1 || regs[1]->unit == UNIT_RAM_D1)
5154 du = 1;
5156 if (is_accumulator_reg(regs[0]) && !(template->arg_type & DSP_ARGS_DACC))
5158 as_bad (_("accumulator not a valid destination"));
5159 return NULL;
5162 /* Check for immediate, e.g. De.r,Dx.r,#I16 */
5163 if (*l == IMM_CHAR)
5165 l = parse_imm16 (l, insn, &imm);
5166 if (l == NULL)
5168 as_bad (_("invalid immediate value"));
5169 return NULL;
5172 if (!within_signed_range (imm, IMM16_BITS))
5174 as_bad (_("immediate value out of range"));
5175 return NULL;
5178 if (regs[0]->unit != regs[1]->unit || regs[0]->no != regs[1]->no)
5180 as_bad (_("immediate value not allowed when source & dest differ"));
5181 return NULL;
5184 imm_mask = 0xffff;
5185 imm_shift = 3;
5187 /* Set the I-bit */
5188 insn->bits |= (1 << 25);
5190 insn->bits |= (0x3 << 0);
5192 l1_shift = 2;
5194 /* Remove any bits that have been set in the immediate
5195 field. */
5196 insn->bits &= ~(imm_mask << imm_shift);
5198 else
5201 regs_shift[1] = 14;
5202 regs_shift[2] = 9;
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)
5208 l = ll;
5210 if (!(template->arg_type & DSP_ARGS_ACC2))
5212 as_bad (_("invalid register operand: %s"), regs[2]->name);
5213 return NULL;
5216 om_shift = 3;
5217 ar_shift = 7;
5218 ar = true;
5220 else
5222 /* De.r,Dx.r,De.r */
5223 l = __parse_gp_reg (l, &regs[2], true);
5224 if (l == NULL)
5225 return NULL;
5228 if (template->arg_type & DSP_ARGS_ACC2)
5229 om_shift = 3;
5231 /* Is this a QUICKRoT instruction? De.r,Dx.r,De.r[,Ae.r] */
5232 if (template->arg_type & DSP_ARGS_QR)
5234 if (conditional)
5235 qn_shift = 5;
5236 else
5238 qn_shift = 7;
5239 qr_shift = 6;
5240 qd_shift = 5;
5243 l = skip_comma (l);
5244 if (l == NULL)
5246 as_bad (_("QUICKRoT extension requires 4 registers"));
5247 return NULL;
5250 l = __parse_gp_reg (l, &regs[3], true);
5251 if (l == NULL)
5253 as_bad (_("invalid fourth register"));
5254 return NULL;
5257 if (!is_addr_unit (regs[3]->unit) ||
5258 !is_quickrot_reg (regs[3]->no))
5260 as_bad (_("A0.2,A0.3,A1.2,A1.3 required for QUICKRoT register"));
5261 return NULL;
5264 qn = (regs[3]->no == 3);
5268 check_for_template:
5269 /* This is the common exit path. Check for o2r. */
5270 if (regs[2] != NULL)
5272 o2r = units_need_o2r (regs[1]->unit, regs[2]->unit);
5273 if (o2r)
5275 o2r_reg.no = lookup_o2r (0, du, regs[2]);
5276 o2r_reg.unit = regs[2]->unit;
5277 regs[2] = &o2r_reg;
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;
5292 /* Is this a template definition? */
5293 if (IS_TEMPLATE_DEF (insn))
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);
5299 if (l == NULL)
5300 return NULL;
5302 if (!dspram)
5303 mx_shift = 0;
5306 goto matched;
5309 /* Group 2. */
5310 if (template->arg_type & DSP_ARGS_2)
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;
5317 if (is_xsd)
5318 du_shift = 0;
5319 else
5320 du_shift = 24;
5322 l1_shift = 4;
5324 /* CMPs and TSTs don't store to their destination operand. */
5325 ll = __parse_gp_reg (l, regs, is_cmp);
5326 if (ll == NULL)
5328 /* DSPe.r,Dx.r or DSPx.r,#I16 */
5329 if (template->arg_type & DSP_ARGS_DSP_SRC1)
5331 l = parse_dsp_reg (l, regs, false, false);
5332 if (l == NULL)
5334 as_bad (_("invalid register operand #1"));
5335 return NULL;
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;
5346 else
5348 as_bad (_("invalid register operand #2"));
5349 return NULL;
5352 else
5354 l = ll;
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;
5367 if (!is_dsp_data_unit (regs[0]) && !(regs[0]->unit == UNIT_FX &&
5368 is_fpu_mov && to_fpu))
5369 return NULL;
5371 du = (regs[0]->unit == UNIT_D1 || regs[0]->unit == UNIT_RAM_D1 ||
5372 regs[0]->unit == UNIT_ACC_D1);
5374 l = skip_comma (l);
5376 if (*l == IMM_CHAR)
5378 if (template->arg_type & DSP_ARGS_IMM &&
5379 !(is_mov && (MAJOR_OPCODE (insn->bits) != OPC_9)))
5381 l = parse_imm16 (l, insn, &imm);
5382 if (l == NULL)
5384 as_bad (_("invalid immediate value"));
5385 return NULL;
5388 if (!within_signed_range (imm, IMM16_BITS))
5389 return NULL;
5391 l1_shift = 2;
5392 regs_shift[0] = 19;
5394 imm_mask = 0xffff;
5395 imm_shift = 3;
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);
5402 /* All instructions that takes immediates also have bit 1 set. */
5403 insn->bits |= (1 << 1);
5405 if (MAJOR_OPCODE (insn->bits) != OPC_9)
5406 insn->bits |= (1 << 0);
5408 insn->bits &= ~(1 << 8);
5410 else
5412 as_bad (_("this instruction does not accept an immediate"));
5413 return NULL;
5416 else
5418 if (MAJOR_OPCODE (insn->bits) != OPC_9)
5420 insn->bits |= (1 << 8);
5421 l1_shift = 4;
5424 ll = __parse_gp_reg (l, &regs[1], true);
5425 if (ll == NULL)
5427 if (template->arg_type & DSP_ARGS_DSP_SRC2)
5429 l = parse_dsp_reg (l, &regs[1], false, false);
5430 if (l == NULL)
5432 as_bad (_("invalid register operand #3"));
5433 return NULL;
5436 /* MOV and NEG. */
5437 if ((is_mov && (MAJOR_OPCODE (insn->bits) != OPC_9)) ||
5438 MAJOR_OPCODE (template->meta_opcode) == OPC_SUB)
5440 if (is_accumulator_reg (regs[1]))
5442 if (is_fpu_mov)
5444 as_bad (_("this instruction does not accept an accumulator"));
5445 return NULL;
5447 ar_shift = 7;
5448 ar = 1;
5449 regs_shift[1] = 9;
5451 else
5453 du_shift = 0;
5454 l1_shift = 2;
5455 regs_shift[1] = 14;
5456 insn->bits = 0x92u << 24; /* Set opcode. */
5460 else
5462 as_bad (_("invalid register operand #4"));
5463 return NULL;
5466 else
5468 /* Set the o2r bit if required. */
5469 if (!is_fpu_mov && units_need_o2r (regs[0]->unit, regs[1]->unit))
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;
5477 else if (!is_dsp_data_unit (regs[1]) &&
5478 !(is_fpu_mov && !to_fpu && regs[1]->unit == UNIT_FX))
5479 return NULL;
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);
5486 l = ll;
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;
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)
5502 om_shift = 3;
5503 sc_shift = 5;
5504 insn->bits |= (1 << 2);
5507 /* Check for template definitions. */
5508 if (IS_TEMPLATE_DEF (insn))
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;
5515 if (l == NULL)
5516 return NULL;
5518 goto matched;
5521 /* Group 3. */
5522 du_shift = 24;
5523 l1_shift = 4;
5525 l = __parse_gp_reg (l, regs, false);
5526 if (l == NULL)
5528 as_bad (_("invalid register operand"));
5529 return NULL;
5532 l = skip_comma (l);
5534 if (*l == 'A')
5536 l = parse_dsp_reg (l, &regs[1], false, false);
5537 if (l == NULL)
5539 as_bad (_("invalid accumulator register"));
5540 return NULL;
5542 ac = 1;
5543 ac_shift = 0;
5545 else
5547 l = __parse_gp_reg (l, &regs[1], true);
5548 if (l == NULL)
5550 as_bad (_("invalid register operand"));
5551 return NULL;
5555 regs_shift[0] = 19;
5556 regs_shift[1] = 14;
5558 du = (regs[1]->unit == UNIT_D1 || regs[1]->unit == UNIT_ACC_D1
5559 || regs[1]->unit == UNIT_RAM_D1);
5561 l = skip_comma (l);
5563 if (*l == IMM_CHAR)
5565 l = parse_imm_constant (l, insn, &imm);
5566 if (l == NULL)
5568 as_bad (_("invalid immediate value"));
5569 return NULL;
5572 if (!within_unsigned_range (imm, IMM5_BITS))
5573 return NULL;
5575 imm_mask = 0x1f;
5576 imm_shift = 9;
5578 /* Set the I-bit */
5579 insn->bits |= (1 << 25);
5581 else
5583 regs_shift[2] = 9;
5584 l = __parse_gp_reg (l, &regs[2], true);
5585 if (l == NULL)
5586 return NULL;
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)
5593 if ((template->meta_opcode >> 26) & 0x1)
5595 as_bad (_("conditional instruction cannot use G flag"));
5596 return NULL;
5599 insn->bits |= (1 << 3);
5602 if (insn->dsp_action_flags & DSP_ACTION_CLAMP8)
5604 if ((template->meta_opcode >> 26) & 0x1)
5606 as_bad (_("conditional instruction cannot use B flag"));
5607 return NULL;
5610 insn->bits |= (0x3 << 2);
5613 if (insn->dsp_action_flags & DSP_ACTION_ROUND)
5615 if ((template->meta_opcode >> 26) & 0x1)
5617 as_bad (_("conditional instruction cannot use R flag"));
5618 return NULL;
5620 insn->bits |= (1 << 2);
5623 /* Conditional Data Unit Shift instructions cannot be dual unit. */
5624 if ((template->meta_opcode >> 26) & 0x1)
5625 ls_shift = INVALID_SHIFT;
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))
5632 /* Set both the Conditional bit and the Condition is Always bit. */
5633 insn->bits |= (1 << 26);
5634 insn->bits |= (1 << 5);
5636 /* Fill out the Ud field. */
5637 insn->bits |= (regs[0]->unit << 1);
5640 if (IS_TEMPLATE_DEF (insn))
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);
5646 if (l == NULL)
5647 return NULL;
5649 if (!dspram)
5650 mx_shift = 5;
5653 /* Fall through. */
5654 matched:
5656 /* Set the registers and immediate values. */
5657 if (regs_shift[0] != INVALID_SHIFT)
5658 insn->bits |= (regs[0]->no << regs_shift[0]);
5660 if (regs_shift[1] != INVALID_SHIFT)
5661 insn->bits |= (regs[1]->no << regs_shift[1]);
5663 if (regs_shift[2] != INVALID_SHIFT)
5664 insn->bits |= (regs[2]->no << regs_shift[2]);
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);
5671 /* Does this insn have an 'AU' bit? */
5672 if (au_shift != INVALID_SHIFT)
5673 insn->bits |= (au << au_shift);
5675 /* Does this instruction have an 'LS' bit? */
5676 if (ls_shift != INVALID_SHIFT)
5677 insn->bits |= (load << ls_shift);
5679 /* Does this instruction have an 'AR' bit? */
5680 if (ar)
5681 insn->bits |= (1 << ar_shift);
5683 if (du_shift != INVALID_SHIFT)
5684 insn->bits |= (du << du_shift);
5686 if (sc_shift != INVALID_SHIFT)
5687 insn->bits |= (sc << sc_shift);
5689 if (om_shift != INVALID_SHIFT)
5690 insn->bits |= (om << om_shift);
5692 if (o2r_shift != INVALID_SHIFT)
5693 insn->bits |= (o2r << o2r_shift);
5695 if (qn_shift != INVALID_SHIFT)
5696 insn->bits |= (qn << qn_shift);
5698 if (qr_shift != INVALID_SHIFT)
5699 insn->bits |= (qr << qr_shift);
5701 if (qd_shift != INVALID_SHIFT)
5702 insn->bits |= (is_quickrot64 << qd_shift);
5704 if (a1_shift != INVALID_SHIFT)
5705 insn->bits |= (a1 << a1_shift);
5707 if (a2_shift != INVALID_SHIFT)
5708 insn->bits |= (a2 << a2_shift);
5710 if (su_shift != INVALID_SHIFT)
5711 insn->bits |= (su << su_shift);
5713 if (imm_shift != INVALID_SHIFT)
5714 insn->bits |= ((imm & imm_mask) << imm_shift);
5716 if (ac_shift != INVALID_SHIFT)
5717 insn->bits |= (ac << ac_shift);
5719 if (mx_shift != INVALID_SHIFT)
5720 insn->bits |= (mx << mx_shift);
5722 if (is_dual)
5724 if (l1_shift == INVALID_SHIFT)
5726 as_bad (_("'L' modifier not valid for this instruction"));
5727 return NULL;
5730 insn->bits |= (1 << l1_shift);
5733 insn->len = 4;
5735 return l;
5738 typedef const char *(*insn_parser)(const char *, metag_insn *,
5739 const insn_template *);
5741 /* Parser table. */
5742 static const insn_parser insn_parsers[ENC_MAX] =
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,
5791 struct metag_core_option
5793 const char *name;
5794 unsigned int value;
5797 /* CPU type options. */
5798 static const struct metag_core_option metag_cpus[] =
5800 {"all", CoreMeta11|CoreMeta12|CoreMeta21},
5801 {"metac11", CoreMeta11},
5802 {"metac12", CoreMeta12},
5803 {"metac21", CoreMeta21},
5804 {NULL, 0},
5807 /* FPU type options. */
5808 static const struct metag_core_option metag_fpus[] =
5810 {"metac21", FpuMeta21},
5811 {NULL, 0},
5814 /* DSP type options. */
5815 static const struct metag_core_option metag_dsps[] =
5817 {"metac21", DspMeta21},
5818 {NULL, 0},
5821 /* Parse a CPU command line option. */
5822 static bool
5823 metag_parse_cpu (const char * str)
5825 const struct metag_core_option * opt;
5826 int optlen;
5828 optlen = strlen (str);
5830 if (optlen == 0)
5832 as_bad (_("missing cpu name `%s'"), str);
5833 return 0;
5836 for (opt = metag_cpus; opt->name != NULL; opt++)
5837 if (strncmp (opt->name, str, optlen) == 0)
5839 mcpu_opt = opt->value;
5840 return 1;
5843 as_bad (_("unknown cpu `%s'"), str);
5844 return 0;
5847 /* Parse an FPU command line option. */
5848 static bool
5849 metag_parse_fpu (const char * str)
5851 const struct metag_core_option * opt;
5852 int optlen;
5854 optlen = strlen (str);
5856 if (optlen == 0)
5858 as_bad (_("missing fpu name `%s'"), str);
5859 return 0;
5862 for (opt = metag_fpus; opt->name != NULL; opt++)
5863 if (strncmp (opt->name, str, optlen) == 0)
5865 mfpu_opt = opt->value;
5866 return 1;
5869 as_bad (_("unknown fpu `%s'"), str);
5870 return 0;
5873 /* Parse a DSP command line option. */
5874 static bool
5875 metag_parse_dsp (const char * str)
5877 const struct metag_core_option * opt;
5878 int optlen;
5880 optlen = strlen (str);
5882 if (optlen == 0)
5884 as_bad (_("missing DSP name `%s'"), str);
5885 return 0;
5888 for (opt = metag_dsps; opt->name != NULL; opt++)
5889 if (strncmp (opt->name, str, optlen) == 0)
5891 mdsp_opt = opt->value;
5892 return 1;
5895 as_bad (_("unknown DSP `%s'"), str);
5896 return 0;
5899 struct metag_long_option
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. */
5907 struct metag_long_option metag_long_opts[] =
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}
5919 md_parse_option (int c, const char * arg)
5921 struct metag_long_option *lopt;
5923 for (lopt = metag_long_opts; lopt->option != NULL; lopt++)
5925 /* These options are expected to have an argument. */
5926 if (c == lopt->option[0]
5927 && arg != NULL
5928 && startswith (arg, lopt->option + 1))
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
5937 /* Call the sup-option parser. */
5938 return lopt->func (arg + strlen (lopt->option) - 1);
5942 return 0;
5945 void
5946 md_show_usage (FILE * stream)
5948 struct metag_long_option *lopt;
5950 fprintf (stream, _(" Meta specific command line options:\n"));
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));
5957 /* The target specific pseudo-ops which we support. */
5958 const pseudo_typeS md_pseudo_table[] =
5960 { "word", cons, 2 },
5961 { NULL, NULL, 0 }
5964 void
5965 md_begin (void)
5967 int c;
5969 for (c = 0; c < 256; c++)
5971 if (ISDIGIT (c))
5973 register_chars[c] = c;
5974 /* LOCK0, LOCK1, LOCK2. */
5975 mnemonic_chars[c] = c;
5977 else if (ISLOWER (c))
5979 register_chars[c] = c;
5980 mnemonic_chars[c] = c;
5982 else if (ISUPPER (c))
5984 register_chars[c] = c;
5985 mnemonic_chars[c] = c;
5987 else if (c == '.')
5989 register_chars[c] = c;
5994 /* Parse a split condition code prefix. */
5995 static const char *
5996 parse_split_condition (const char *line, metag_insn *insn)
5998 const char *l = line;
5999 const split_condition *scond;
6000 split_condition entry;
6001 char buf[4];
6003 memcpy (buf, l, 4);
6004 buf[3] = '\0';
6006 entry.name = buf;
6008 scond = (const split_condition *) htab_find (scond_htab, &entry);
6010 if (!scond)
6011 return NULL;
6013 insn->scond = scond->code;
6015 return l + strlen (scond->name);
6018 /* Parse an instruction prefix - F for float, D for DSP - and associated
6019 flags and condition codes. */
6020 static const char *
6021 parse_prefix (const char *line, metag_insn *insn)
6023 const char *l = line;
6025 l = skip_whitespace (l);
6027 insn->type = INSN_GP;
6029 if (TOLOWER (*l) == FPU_PREFIX_CHAR)
6031 if (strncasecmp (l, FFB_INSN, strlen(FFB_INSN)))
6033 insn->type = INSN_FPU;
6035 l++;
6037 if (*l == END_OF_INSN)
6039 as_bad (_("premature end of floating point prefix"));
6040 return NULL;
6043 if (TOLOWER (*l) == FPU_DOUBLE_CHAR)
6045 insn->fpu_width = FPU_WIDTH_DOUBLE;
6046 l++;
6048 else if (TOLOWER (*l) == FPU_PAIR_CHAR)
6050 const char *l2 = l;
6052 /* Check this isn't a split condition beginning with L. */
6053 l2 = parse_split_condition (l2, insn);
6055 if (l2 && is_whitespace_char (*l2))
6057 l = l2;
6059 else
6061 insn->fpu_width = FPU_WIDTH_PAIR;
6062 l++;
6065 else
6067 insn->fpu_width = FPU_WIDTH_SINGLE;
6070 if (TOLOWER (*l) == FPU_ACTION_ABS_CHAR)
6072 insn->fpu_action_flags |= FPU_ACTION_ABS;
6073 l++;
6075 else if (TOLOWER (*l) == FPU_ACTION_INV_CHAR)
6077 insn->fpu_action_flags |= FPU_ACTION_INV;
6078 l++;
6081 if (TOLOWER (*l) == FPU_ACTION_QUIET_CHAR)
6083 insn->fpu_action_flags |= FPU_ACTION_QUIET;
6084 l++;
6087 if (TOLOWER (*l) == FPU_ACTION_ZERO_CHAR)
6089 insn->fpu_action_flags |= FPU_ACTION_ZERO;
6090 l++;
6093 if (! is_whitespace_char (*l))
6095 l = parse_split_condition (l, insn);
6097 if (!l)
6099 as_bad (_("unknown floating point prefix character"));
6100 return NULL;
6104 l = skip_space (l);
6107 else if (TOLOWER (*l) == DSP_PREFIX_CHAR)
6109 if (strncasecmp (l, DCACHE_INSN, strlen (DCACHE_INSN)) &&
6110 strncasecmp (l, DEFR_INSN, strlen (DEFR_INSN)))
6112 const char *ll = l;
6113 insn->type = INSN_DSP;
6115 l++;
6117 insn->dsp_width = DSP_WIDTH_SINGLE;
6119 while (!is_whitespace_char (*l))
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);
6129 if (l == NULL)
6130 l = ll;
6131 else
6132 continue;
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)
6138 insn->type = INSN_DSP_FPU;
6139 l++;
6140 continue;
6143 if (TOLOWER(*l) == DSP_DUAL_CHAR)
6145 insn->dsp_width = DSP_WIDTH_DUAL;
6146 l++;
6147 continue;
6150 if (TOLOWER(*l) == DSP_ACTION_QR64_CHAR)
6152 insn->dsp_action_flags |= DSP_ACTION_QR64;
6153 l++;
6154 continue;
6157 if (TOLOWER(*l) == DSP_ACTION_UMUL_CHAR)
6159 insn->dsp_action_flags |= DSP_ACTION_UMUL;
6160 l++;
6161 continue;
6164 if (TOLOWER(*l) == DSP_ACTION_ROUND_CHAR)
6166 insn->dsp_action_flags |= DSP_ACTION_ROUND;
6167 l++;
6168 continue;
6171 if (TOLOWER(*l) == DSP_ACTION_CLAMP9_CHAR)
6173 insn->dsp_action_flags |= DSP_ACTION_CLAMP9;
6174 l++;
6175 continue;
6178 if (TOLOWER(*l) == DSP_ACTION_CLAMP8_CHAR)
6180 insn->dsp_action_flags |= DSP_ACTION_CLAMP8;
6181 l++;
6182 continue;
6185 if (TOLOWER(*l) == DSP_ACTION_MOD_CHAR)
6187 insn->dsp_action_flags |= DSP_ACTION_MOD;
6188 l++;
6189 continue;
6192 if (TOLOWER(*l) == DSP_ACTION_ACC_ZERO_CHAR)
6194 insn->dsp_action_flags |= DSP_ACTION_ACC_ZERO;
6195 l++;
6196 continue;
6199 if (TOLOWER(*l) == DSP_ACTION_ACC_ADD_CHAR)
6201 insn->dsp_action_flags |= DSP_ACTION_ACC_ADD;
6202 l++;
6203 continue;
6206 if (TOLOWER(*l) == DSP_ACTION_ACC_SUB_CHAR)
6208 insn->dsp_action_flags |= DSP_ACTION_ACC_SUB;
6209 l++;
6210 continue;
6213 if (TOLOWER(*l) == DSP_ACTION_OV_CHAR)
6215 insn->dsp_action_flags |= DSP_ACTION_OV;
6216 l++;
6217 continue;
6220 if (TOLOWER(*l) == DSP_DAOPPAME_8_CHAR)
6222 insn->dsp_daoppame_flags |= DSP_DAOPPAME_8;
6223 l++;
6224 continue;
6227 if (TOLOWER(*l) == DSP_DAOPPAME_16_CHAR)
6229 insn->dsp_daoppame_flags |= DSP_DAOPPAME_16;
6230 l++;
6231 continue;
6234 if (TOLOWER(*l) == DSP_DAOPPAME_TEMP_CHAR)
6236 insn->dsp_daoppame_flags |= DSP_DAOPPAME_TEMP;
6237 l++;
6238 continue;
6241 if (TOLOWER(*l) == DSP_DAOPPAME_HIGH_CHAR)
6243 insn->dsp_daoppame_flags |= DSP_DAOPPAME_HIGH;
6244 l++;
6245 continue;
6248 as_bad (_("unknown DSP prefix character %c %s"), *l, l);
6249 return NULL;
6252 l = skip_space (l);
6256 return l;
6259 /* Return a list of appropriate instruction parsers for MNEMONIC. */
6260 static insn_templates *
6261 find_insn_templates (const char *mnemonic)
6263 insn_template template;
6264 insn_templates entry;
6265 insn_templates *slot;
6267 entry.template = &template;
6269 memcpy ((void *)&entry.template->name, &mnemonic, sizeof (char *));
6271 slot = (insn_templates *) htab_find (mnemonic_htab, &entry);
6273 if (slot)
6274 return slot;
6276 return NULL;
6279 /* Make an uppercase copy of SRC into DST and return DST. */
6280 static char *
6281 strupper (char * dst, const char *src)
6283 size_t i = 0;
6285 while (src[i])
6287 dst[i] = TOUPPER (src[i]);
6288 i++;
6291 dst[i] = 0;
6293 return dst;
6296 /* Calculate a hash value for a template. */
6297 static hashval_t
6298 hash_templates (const void *p)
6300 insn_templates *tp = (insn_templates *)p;
6301 char buf[MAX_MNEMONIC_LEN];
6303 strupper (buf, tp->template->name);
6305 return htab_hash_string (buf);
6308 /* Check if two templates are equal. */
6309 static int
6310 eq_templates (const void *a, const void *b)
6312 insn_templates *ta = (insn_templates *)a;
6313 insn_templates *tb = (insn_templates *)b;
6314 return strcasecmp (ta->template->name, tb->template->name) == 0;
6317 /* Create the hash table required for parsing instructions. */
6318 static void
6319 create_mnemonic_htab (void)
6321 size_t i, num_templates = sizeof(metag_optab)/sizeof(metag_optab[0]);
6323 mnemonic_htab = htab_create_alloc (num_templates, hash_templates,
6324 eq_templates, NULL, xcalloc, free);
6326 for (i = 0; i < num_templates; i++)
6328 const insn_template *template = &metag_optab[i];
6329 insn_templates **slot = NULL;
6330 insn_templates *new_entry;
6332 new_entry = XNEW (insn_templates);
6334 new_entry->template = template;
6335 new_entry->next = NULL;
6337 slot = (insn_templates **) htab_find_slot (mnemonic_htab, new_entry,
6338 INSERT);
6340 if (*slot)
6342 insn_templates *last_entry = *slot;
6344 while (last_entry->next)
6345 last_entry = last_entry->next;
6347 last_entry->next = new_entry;
6349 else
6351 *slot = new_entry;
6356 /* Calculate a hash value for a register. */
6357 static hashval_t
6358 hash_regs (const void *p)
6360 metag_reg *rp = (metag_reg *)p;
6361 char buf[MAX_REG_LEN];
6363 strupper (buf, rp->name);
6365 return htab_hash_string (buf);
6368 /* Check if two registers are equal. */
6369 static int
6370 eq_regs (const void *a, const void *b)
6372 metag_reg *ra = (metag_reg *)a;
6373 metag_reg *rb = (metag_reg *)b;
6374 return strcasecmp (ra->name, rb->name) == 0;
6377 /* Create the hash table required for parsing registers. */
6378 static void
6379 create_reg_htab (void)
6381 size_t i, num_regs = sizeof(metag_regtab)/sizeof(metag_regtab[0]);
6383 reg_htab = htab_create_alloc (num_regs, hash_regs,
6384 eq_regs, NULL, xcalloc, free);
6386 for (i = 0; i < num_regs; i++)
6388 const metag_reg *reg = &metag_regtab[i];
6389 const metag_reg **slot;
6391 slot = (const metag_reg **) htab_find_slot (reg_htab, reg, INSERT);
6393 if (!*slot)
6394 *slot = reg;
6398 /* Create the hash table required for parsing DSP registers. */
6399 static void
6400 create_dspreg_htabs (void)
6402 size_t i, num_regs = sizeof(metag_dsp_regtab)/sizeof(metag_dsp_regtab[0]);
6403 size_t h;
6405 dsp_reg_htab = htab_create_alloc (num_regs, hash_regs,
6406 eq_regs, NULL, xcalloc, free);
6408 for (i = 0; i < num_regs; i++)
6410 const metag_reg *reg = &metag_dsp_regtab[i];
6411 const metag_reg **slot;
6413 slot = (const metag_reg **) htab_find_slot (dsp_reg_htab, reg, INSERT);
6415 /* Make sure there are no hash table collisions, which would
6416 require chaining entries. */
6417 gas_assert (*slot == NULL);
6418 *slot = reg;
6421 num_regs = sizeof(metag_dsp_tmpl_regtab[0])/sizeof(metag_dsp_tmpl_regtab[0][0]);
6423 for (h = 0; h < 2; h++)
6425 dsp_tmpl_reg_htab[h] = htab_create_alloc (num_regs, hash_regs,
6426 eq_regs, NULL, xcalloc, free);
6429 for (h = 0; h < 2; h++)
6431 for (i = 0; i < num_regs; i++)
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);
6438 /* Make sure there are no hash table collisions, which would
6439 require chaining entries. */
6440 gas_assert (*slot == NULL);
6441 *slot = reg;
6446 /* Calculate a hash value for a split condition code. */
6447 static hashval_t
6448 hash_scond (const void *p)
6450 split_condition *cp = (split_condition *)p;
6451 char buf[4];
6453 strupper (buf, cp->name);
6455 return htab_hash_string (buf);
6458 /* Check if two split condition codes are equal. */
6459 static int
6460 eq_scond (const void *a, const void *b)
6462 split_condition *ra = (split_condition *)a;
6463 split_condition *rb = (split_condition *)b;
6465 return strcasecmp (ra->name, rb->name) == 0;
6468 /* Create the hash table required for parsing split condition codes. */
6469 static void
6470 create_scond_htab (void)
6472 size_t i, nentries;
6474 nentries = sizeof (metag_scondtab) / sizeof (metag_scondtab[0]);
6476 scond_htab = htab_create_alloc (nentries, hash_scond, eq_scond,
6477 NULL, xcalloc, free);
6478 for (i = 0; i < nentries; i++)
6480 const split_condition *scond = &metag_scondtab[i];
6481 const split_condition **slot;
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;
6492 /* Entry point for instruction parsing. */
6493 static bool
6494 parse_insn (const char *line, metag_insn *insn)
6496 char mnemonic[MAX_MNEMONIC_LEN];
6497 const char *l = line;
6498 size_t mnemonic_len = 0;
6499 insn_templates *templates;
6501 l = skip_space (l);
6503 while (is_mnemonic_char(*l))
6505 l++;
6506 mnemonic_len++;
6509 if (mnemonic_len >= MAX_MNEMONIC_LEN)
6511 as_bad (_("instruction mnemonic too long: %s"), line);
6512 return false;
6515 strncpy(mnemonic, line, mnemonic_len);
6517 mnemonic[mnemonic_len] = '\0';
6519 templates = find_insn_templates (mnemonic);
6521 if (templates)
6523 insn_templates *current_template = templates;
6525 l = skip_space (l);
6527 while (current_template)
6529 const insn_template *template = current_template->template;
6530 enum insn_encoding encoding = template->encoding;
6531 insn_parser parser = insn_parsers[encoding];
6533 current_template = current_template->next;
6535 if (template->insn_type == INSN_GP &&
6536 !(template->core_flags & mcpu_opt))
6537 continue;
6539 if (template->insn_type == INSN_FPU &&
6540 !(template->core_flags & mfpu_opt))
6541 continue;
6543 if (template->insn_type == INSN_DSP &&
6544 !(template->core_flags & mdsp_opt))
6545 continue;
6547 if (template->insn_type == INSN_DSP_FPU &&
6548 !((template->core_flags & mdsp_opt) &&
6549 (template->core_flags & mfpu_opt)))
6550 continue;
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;
6559 if (parser)
6561 const char *end = parser(l, insn, template);
6563 if (end != NULL)
6565 if (*end != END_OF_INSN)
6566 as_bad (_("junk at end of line: \"%s\""), line);
6567 else
6568 return true;
6573 as_bad (_("failed to assemble instruction: \"%s\""), line);
6575 else
6577 if (insn->type == INSN_FPU)
6578 as_bad (_("unknown floating point mnemonic: \"%s\""), mnemonic);
6579 else
6580 as_bad (_("unknown mnemonic: \"%s\""), mnemonic);
6582 return false;
6585 static void
6586 output_insn (metag_insn *insn)
6588 char *output;
6590 output = frag_more (insn->len);
6591 dwarf2_emit_insn (insn->len);
6593 if (insn->reloc_type != BFD_RELOC_UNUSED)
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);
6600 md_number_to_chars (output, insn->bits, insn->len);
6603 void
6604 md_assemble (char *line)
6606 const char *l = line;
6607 metag_insn insn;
6609 memset (&insn, 0, sizeof(insn));
6611 insn.reloc_type = BFD_RELOC_UNUSED;
6612 insn.reloc_pcrel = 0;
6613 insn.reloc_size = 4;
6615 if (!mnemonic_htab)
6617 create_mnemonic_htab ();
6618 create_reg_htab ();
6619 create_dspreg_htabs ();
6620 create_scond_htab ();
6623 l = parse_prefix (l, &insn);
6625 if (l == NULL)
6626 return;
6628 if (insn.type == INSN_DSP &&
6629 !mdsp_opt)
6631 as_bad (_("cannot assemble DSP instruction, DSP option not set: %s"),
6632 line);
6633 return;
6635 else if (insn.type == INSN_FPU &&
6636 !mfpu_opt)
6638 as_bad (_("cannot assemble FPU instruction, FPU option not set: %s"),
6639 line);
6640 return;
6643 if (!parse_insn (l, &insn))
6644 return;
6646 output_insn (&insn);
6649 void
6650 md_operand (expressionS * expressionP)
6652 if (* input_line_pointer == IMM_CHAR)
6654 input_line_pointer ++;
6655 expression (expressionP);
6659 valueT
6660 md_section_align (segT segment ATTRIBUTE_UNUSED, valueT size)
6662 return size;
6665 symbolS *
6666 md_undefined_symbol (char *name ATTRIBUTE_UNUSED)
6668 return NULL;
6671 /* Functions concerning relocs. */
6673 /* The location from which a PC relative jump should be calculated,
6674 given a PC relative reloc. */
6676 long
6677 md_pcrel_from_section (fixS * fixP, segT sec)
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))
6684 /* The symbol is undefined (or is defined but not in this section).
6685 Let the linker figure it out. */
6686 return 0;
6689 return fixP->fx_frag->fr_address + fixP->fx_where;
6692 /* Write a value out to the object file, using the appropriate endianness. */
6694 void
6695 md_number_to_chars (char * buf, valueT val, int n)
6697 number_to_chars_littleendian (buf, val, n);
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.
6705 const char *
6706 md_atof (int type, char * litP, int * sizeP)
6708 int i;
6709 int prec;
6710 LITTLENUM_TYPE words [MAX_LITTLENUMS];
6711 char * t;
6713 switch (type)
6715 case 'f':
6716 case 'F':
6717 case 's':
6718 case 'S':
6719 prec = 2;
6720 break;
6722 case 'd':
6723 case 'D':
6724 case 'r':
6725 case 'R':
6726 prec = 4;
6727 break;
6729 /* FIXME: Some targets allow other format chars for bigger sizes here. */
6731 default:
6732 * sizeP = 0;
6733 return _("Bad call to md_atof()");
6736 t = atof_ieee (input_line_pointer, type, words);
6737 if (t)
6738 input_line_pointer = t;
6739 * sizeP = prec * sizeof (LITTLENUM_TYPE);
6741 for (i = 0; i < prec; i++)
6743 md_number_to_chars (litP, (valueT) words[i],
6744 sizeof (LITTLENUM_TYPE));
6745 litP += sizeof (LITTLENUM_TYPE);
6748 return 0;
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. */
6757 metag_force_relocation (fixS * fix)
6759 switch (fix->fx_r_type)
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:
6772 return generic_force_reloc (fix);
6775 bool
6776 metag_fix_adjustable (fixS * fixP)
6778 if (fixP->fx_addsy == NULL)
6779 return 1;
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;
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;
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;
6803 return 1;
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.
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. */
6818 md_estimate_size_before_relax (fragS * fragP ATTRIBUTE_UNUSED,
6819 segT segment ATTRIBUTE_UNUSED)
6821 /* No assembler relaxation is defined (or necessary) for this port. */
6822 abort ();
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.
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. */
6832 void
6833 md_convert_frag (bfd * abfd ATTRIBUTE_UNUSED, segT sec ATTRIBUTE_UNUSED,
6834 fragS * fragP ATTRIBUTE_UNUSED)
6836 /* No assembler relaxation is defined (or necessary) for this port. */
6837 abort ();
6840 /* This is called from HANDLE_ALIGN in tc-metag.h. */
6842 void
6843 metag_handle_align (fragS * fragP)
6845 static unsigned char const noop[4] = { 0xfe, 0xff, 0xff, 0xa0 };
6846 int bytes, fix;
6847 char *p;
6849 if (fragP->fr_type != rs_align_code)
6850 return;
6852 bytes = fragP->fr_next->fr_address - fragP->fr_address - fragP->fr_fix;
6853 p = fragP->fr_literal + fragP->fr_fix;
6854 fix = 0;
6856 if (bytes & 3)
6858 fix = bytes & 3;
6859 memset (p, 0, fix);
6860 p += fix;
6861 bytes -= fix;
6864 while (bytes >= 4)
6866 memcpy (p, noop, 4);
6867 p += 4;
6868 bytes -= 4;
6869 fix += 4;
6872 fragP->fr_fix += fix;
6873 fragP->fr_var = 4;
6876 static char *
6877 metag_end_of_match (char * cont, const char * what)
6879 int len = strlen (what);
6881 if (strncasecmp (cont, what, strlen (what)) == 0
6882 && ! is_part_of_name (cont[len]))
6883 return cont + len;
6885 return NULL;
6889 metag_parse_name (char const * name, expressionS * exprP, enum expr_mode mode,
6890 char * nextcharP)
6892 char *next = input_line_pointer;
6893 char *next_end;
6894 int reloc_type;
6895 operatorT op_type;
6896 segT segment;
6898 exprP->X_op_symbol = NULL;
6899 exprP->X_md = BFD_RELOC_UNUSED;
6901 if (strcmp (name, GOT_NAME) == 0)
6903 if (! GOT_symbol)
6904 GOT_symbol = symbol_find_or_make (name);
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 (!expr_defer_p (mode) && segment == absolute_section)
6913 exprP->X_op = O_constant;
6914 exprP->X_add_number = S_GET_VALUE (exprP->X_add_symbol);
6915 exprP->X_add_symbol = NULL;
6917 else if (!expr_defer_p (mode) && segment == reg_section)
6919 exprP->X_op = O_register;
6920 exprP->X_add_number = S_GET_VALUE (exprP->X_add_symbol);
6921 exprP->X_add_symbol = NULL;
6923 else
6925 exprP->X_op = O_symbol;
6926 exprP->X_add_number = 0;
6929 return 1;
6932 exprP->X_add_symbol = symbol_find_or_make (name);
6934 if (*nextcharP != '@')
6935 goto no_suffix;
6936 else if ((next_end = metag_end_of_match (next + 1, "GOTOFF")))
6938 reloc_type = BFD_RELOC_METAG_GOTOFF;
6939 op_type = O_PIC_reloc;
6941 else if ((next_end = metag_end_of_match (next + 1, "GOT")))
6943 reloc_type = BFD_RELOC_METAG_GETSET_GOT;
6944 op_type = O_PIC_reloc;
6946 else if ((next_end = metag_end_of_match (next + 1, "PLT")))
6948 reloc_type = BFD_RELOC_METAG_PLT;
6949 op_type = O_PIC_reloc;
6951 else if ((next_end = metag_end_of_match (next + 1, "TLSGD")))
6953 reloc_type = BFD_RELOC_METAG_TLS_GD;
6954 op_type = O_PIC_reloc;
6956 else if ((next_end = metag_end_of_match (next + 1, "TLSLDM")))
6958 reloc_type = BFD_RELOC_METAG_TLS_LDM;
6959 op_type = O_PIC_reloc;
6961 else if ((next_end = metag_end_of_match (next + 1, "TLSLDO")))
6963 reloc_type = BFD_RELOC_METAG_TLS_LDO;
6964 op_type = O_PIC_reloc;
6966 else if ((next_end = metag_end_of_match (next + 1, "TLSIE")))
6968 reloc_type = BFD_RELOC_METAG_TLS_IE;
6969 op_type = O_PIC_reloc;
6971 else if ((next_end = metag_end_of_match (next + 1, "TLSIENONPIC")))
6973 reloc_type = BFD_RELOC_METAG_TLS_IENONPIC;
6974 op_type = O_PIC_reloc; /* FIXME: is this correct? */
6976 else if ((next_end = metag_end_of_match (next + 1, "TLSLE")))
6978 reloc_type = BFD_RELOC_METAG_TLS_LE;
6979 op_type = O_PIC_reloc;
6981 else
6982 goto no_suffix;
6984 *input_line_pointer = *nextcharP;
6985 input_line_pointer = next_end;
6986 *nextcharP = *input_line_pointer;
6987 *input_line_pointer = '\0';
6989 exprP->X_op = op_type;
6990 exprP->X_add_number = 0;
6991 exprP->X_md = reloc_type;
6993 return 1;
6996 /* If while processing a fixup, a reloc really needs to be created
6997 then it is done here. */
6999 arelent *
7000 tc_gen_reloc (asection *seg ATTRIBUTE_UNUSED, fixS *fixp)
7002 arelent *reloc;
7004 reloc = notes_alloc (sizeof (arelent));
7005 reloc->sym_ptr_ptr = notes_alloc (sizeof (asymbol *));
7006 *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
7007 reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
7009 reloc->addend = fixp->fx_offset;
7010 reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type);
7012 if (reloc->howto == (reloc_howto_type *) NULL)
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 return NULL;
7021 return reloc;
7024 static unsigned int
7025 md_chars_to_number (char *val, int n)
7027 unsigned int retval;
7028 unsigned char * where = (unsigned char *) val;
7030 for (retval = 0; n--;)
7032 retval <<= 8;
7033 retval |= where[n];
7035 return retval;
7038 void
7039 md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
7041 char *buf = fixP->fx_where + fixP->fx_frag->fr_literal;
7042 int value = (int)*valP;
7044 switch (fixP->fx_r_type)
7046 case BFD_RELOC_METAG_TLS_GD:
7047 case BFD_RELOC_METAG_TLS_LE_HI16:
7048 case BFD_RELOC_METAG_TLS_LE_LO16:
7049 case BFD_RELOC_METAG_TLS_IE:
7050 case BFD_RELOC_METAG_TLS_IENONPIC_HI16:
7051 case BFD_RELOC_METAG_TLS_IENONPIC_LO16:
7052 case BFD_RELOC_METAG_TLS_LDM:
7053 case BFD_RELOC_METAG_TLS_LDO_HI16:
7054 case BFD_RELOC_METAG_TLS_LDO_LO16:
7055 S_SET_THREAD_LOCAL (fixP->fx_addsy);
7056 /* Fall through */
7058 case BFD_RELOC_METAG_HIADDR16:
7059 case BFD_RELOC_METAG_LOADDR16:
7060 case BFD_RELOC_VTABLE_INHERIT:
7061 case BFD_RELOC_VTABLE_ENTRY:
7062 fixP->fx_done = false;
7063 break;
7065 case BFD_RELOC_METAG_REL8:
7066 if (!within_unsigned_range (value, IMM8_BITS))
7068 as_bad_where (fixP->fx_file, fixP->fx_line,
7069 "rel8 out of range %d", value);
7071 else
7073 unsigned int newval;
7074 newval = md_chars_to_number (buf, 4);
7075 newval = (newval & 0xffffc03f) | ((value & IMM8_MASK) << 6);
7076 md_number_to_chars (buf, newval, 4);
7078 break;
7079 case BFD_RELOC_METAG_REL16:
7080 if (!within_unsigned_range (value, IMM16_BITS))
7082 as_bad_where (fixP->fx_file, fixP->fx_line,
7083 "rel16 out of range %d", value);
7085 else
7087 unsigned int newval;
7088 newval = md_chars_to_number (buf, 4);
7089 newval = (newval & 0xfff80007) | ((value & IMM16_MASK) << 3);
7090 md_number_to_chars (buf, newval, 4);
7092 break;
7094 case BFD_RELOC_8:
7095 md_number_to_chars (buf, value, 1);
7096 break;
7097 case BFD_RELOC_16:
7098 md_number_to_chars (buf, value, 2);
7099 break;
7100 case BFD_RELOC_32:
7101 md_number_to_chars (buf, value, 4);
7102 break;
7103 case BFD_RELOC_64:
7104 md_number_to_chars (buf, value, 8);
7105 break;
7107 case BFD_RELOC_METAG_RELBRANCH:
7108 if (!value)
7109 break;
7111 value = value / 4;
7113 if (!within_signed_range (value, IMM19_BITS))
7115 as_bad_where (fixP->fx_file, fixP->fx_line,
7116 "relbranch out of range %d", value);
7118 else
7120 unsigned int newval;
7121 newval = md_chars_to_number (buf, 4);
7122 newval = (newval & 0xff00001f) | ((value & IMM19_MASK) << 5);
7123 md_number_to_chars (buf, newval, 4);
7125 break;
7126 default:
7127 break;
7130 if (fixP->fx_addsy == NULL)
7131 fixP->fx_done = true;