1 /* tc-s12z.c -- Assembler code for the Freescale S12Z
2    Copyright (C) 2018-2021 Free Software Foundation, Inc.
3 
4    This file is part of GAS, the GNU Assembler.
5 
6    GAS is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 3, or (at your option)
9    any later version.
10 
11    GAS is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15 
16    You should have received a copy of the GNU General Public License
17    along with GAS; see the file COPYING.  If not, write to
18    the Free Software Foundation, 51 Franklin Street - Fifth Floor,
19    Boston, MA 02110-1301, USA.  */
20 
21 #include "as.h"
22 #include "safe-ctype.h"
23 #include "subsegs.h"
24 #include "dwarf2dbg.h"
25 #include "opcode/s12z.h"
26 #include <limits.h>
27 
28 const char comment_chars[] = ";";
29 
30 const char line_comment_chars[] = "#*";
31 const char line_separator_chars[] = "";
32 
33 static char * register_prefix = NULL;
34 
35 const char EXP_CHARS[] = "eE";
36 const char FLT_CHARS[] = "dD";
37 
38 static char *fail_line_pointer;
39 
40 /* A wrapper around the standard library's strtol.
41    It converts STR into an integral value.
42    This wrapper deals with literal_prefix_dollar_hex.  */
43 static long
s12z_strtol(const char * str,char ** endptr)44 s12z_strtol (const char *str, char ** endptr)
45 {
46   int base = 0;
47   bool negative = false;
48 
49   long result = 0;
50 
51   char *start = (char *) str;
52 
53   /* In the case where literal_prefix_dollar_hex is TRUE the sign has
54   to be handled explicitly.  Otherwise the string will not be
55   recognised as an integer.  */
56   if (str[0] == '-')
57     {
58       negative = true;
59       ++str;
60     }
61   else if (str[0] == '+')
62     {
63       ++str;
64     }
65 
66   if (literal_prefix_dollar_hex && (str[0] == '$'))
67     {
68       base = 16;
69       str++;
70     }
71 
72   result = strtol (str, endptr, base);
73   if (*endptr == str)
74     {
75       *endptr = start;
76     }
77   if (negative)
78     result = -result;
79 
80   return result;
81 }
82 
83 
84 
85 /* Options and initialization.  */
86 
87 const char *md_shortopts = "";
88 
89 struct option md_longopts[] =
90   {
91 #define OPTION_REG_PREFIX (OPTION_MD_BASE)
92    {"mreg-prefix", required_argument, NULL, OPTION_REG_PREFIX},
93 #define OPTION_DOLLAR_HEX (OPTION_MD_BASE + 1)
94    {"mdollar-hex", no_argument, NULL, OPTION_DOLLAR_HEX},
95    {NULL, no_argument, NULL, 0}
96   };
97 
98 size_t md_longopts_size = sizeof (md_longopts);
99 
100 
101 relax_typeS md_relax_table[] =
102   {
103 
104   };
105 
106 /* This table describes all the machine specific pseudo-ops the assembler
107    has to support.  The fields are:
108    pseudo-op name without dot
109    function to call to execute this pseudo-op
110    Integer arg to pass to the function.  */
111 const pseudo_typeS md_pseudo_table[] =
112   {
113     {0, 0, 0}
114   };
115 
116 
117 /* Get the target cpu for the assembler.  */
118 const char *
s12z_arch_format(void)119 s12z_arch_format (void)
120 {
121   return "elf32-s12z";
122 }
123 
124 enum bfd_architecture
s12z_arch(void)125 s12z_arch (void)
126 {
127   return bfd_arch_s12z;
128 }
129 
130 int
s12z_mach(void)131 s12z_mach (void)
132 {
133   return 0;
134 }
135 
136 /* Listing header selected according to cpu.  */
137 const char *
s12z_listing_header(void)138 s12z_listing_header (void)
139 {
140   return "S12Z GAS ";
141 }
142 
143 void
md_show_usage(FILE * stream)144 md_show_usage (FILE *stream)
145 {
146   fputs (_("\ns12z options:\n"), stream);
147   fputs (_("  -mreg-prefix=PREFIX     set a prefix used to indicate register names (default none)\n"), stream);
148   fputs (_("  -mdollar-hex            the prefix '$' instead of '0x' is used to indicate literal hexadecimal constants\n"), stream);
149 }
150 
151 void
s12z_print_statistics(FILE * file ATTRIBUTE_UNUSED)152 s12z_print_statistics (FILE *file ATTRIBUTE_UNUSED)
153 {
154 }
155 
156 int
md_parse_option(int c,const char * arg)157 md_parse_option (int c, const char *arg)
158 {
159   switch (c)
160     {
161     case OPTION_REG_PREFIX:
162       register_prefix = xstrdup (arg);
163       break;
164     case OPTION_DOLLAR_HEX:
165       literal_prefix_dollar_hex = true;
166       break;
167     default:
168       return 0;
169     }
170   return 1;
171 }
172 
173 symbolS *
md_undefined_symbol(char * name ATTRIBUTE_UNUSED)174 md_undefined_symbol (char *name ATTRIBUTE_UNUSED)
175 {
176   return 0;
177 }
178 
179 const char *
md_atof(int type,char * litP,int * sizeP)180 md_atof (int type, char *litP, int *sizeP)
181 {
182   return ieee_md_atof (type, litP, sizeP, true);
183 }
184 
185 valueT
md_section_align(asection * seg,valueT addr)186 md_section_align (asection *seg, valueT addr)
187 {
188   int align = bfd_section_alignment (seg);
189   return ((addr + (1 << align) - 1) & -(1 << align));
190 }
191 
192 void
md_begin(void)193 md_begin (void)
194 {
195 }
196 
197 void
s12z_init_after_args(void)198 s12z_init_after_args (void)
199 {
200   if (flag_traditional_format)
201     literal_prefix_dollar_hex = true;
202 }
203 
204 /* Builtin help.  */
205 
206 
207 static char *
skip_whites(char * p)208 skip_whites (char *p)
209 {
210   while (*p == ' ' || *p == '\t')
211     p++;
212 
213   return p;
214 }
215 
216 
217 
218 /* Start a new insn that contains at least 'size' bytes.  Record the
219    line information of that insn in the dwarf2 debug sections.  */
220 static char *
s12z_new_insn(int size)221 s12z_new_insn (int size)
222 {
223   char *f = frag_more (size);
224 
225   dwarf2_emit_insn (size);
226 
227   return f;
228 }
229 
230 
231 
232 static bool lex_reg_name (uint16_t which, int *reg);
233 
234 static bool
lex_constant(long * v)235 lex_constant (long *v)
236 {
237   char *end = NULL;
238   char *p = input_line_pointer;
239 
240   /* A constant may not have the same value as a register
241      eg: "d6" */
242   int dummy;
243   if (lex_reg_name (~0, &dummy))
244     {
245       input_line_pointer = p;
246       return false;
247     }
248 
249   errno = 0;
250   *v = s12z_strtol (p, &end);
251   if (errno == 0 && end != p)
252     {
253       input_line_pointer = end;
254       return true;
255     }
256 
257   return false;
258 }
259 
260 static bool
lex_match(char x)261 lex_match (char x)
262 {
263   char *p = input_line_pointer;
264   if (*p != x)
265     return false;
266 
267   input_line_pointer++;
268   return true;
269 }
270 
271 
272 static bool
lex_expression(expressionS * exp)273 lex_expression (expressionS *exp)
274 {
275   char *ilp = input_line_pointer;
276   int dummy;
277   exp->X_op = O_absent;
278 
279   if (lex_match ('#'))
280     goto fail;
281 
282   if (lex_reg_name (~0, &dummy))
283     goto fail;
284 
285   expression (exp);
286   if (exp->X_op != O_absent)
287     return true;
288 
289  fail:
290   fail_line_pointer = input_line_pointer;
291   input_line_pointer = ilp;
292   return false;
293 }
294 
295 /* Immediate operand.
296    If EXP_O is non-null, then a symbolic expression is permitted,
297    in which case, EXP_O will be populated with the parsed expression.
298  */
299 static bool
lex_imm(long * v,expressionS * exp_o)300 lex_imm (long *v, expressionS *exp_o)
301 {
302   char *ilp = input_line_pointer;
303 
304   if (*input_line_pointer != '#')
305     goto fail;
306 
307   input_line_pointer++;
308   expressionS exp;
309   if (!lex_expression (&exp))
310     goto fail;
311 
312   if (exp.X_op != O_constant)
313     {
314       if (!exp_o)
315         as_bad (_("A non-constant expression is not permitted here"));
316       else
317         *exp_o = exp;
318     }
319 
320   *v = exp.X_add_number;
321   return true;
322 
323  fail:
324   fail_line_pointer = input_line_pointer;
325   input_line_pointer = ilp;
326   return false;
327 }
328 
329 /* Short mmediate operand */
330 static bool
lex_imm_e4(long * val)331 lex_imm_e4 (long *val)
332 {
333   char *ilp = input_line_pointer;
334   if ((lex_imm (val, NULL)))
335     {
336       if ((*val == -1) || (*val > 0 && *val <= 15))
337 	{
338 	  return true;
339 	}
340     }
341   fail_line_pointer = input_line_pointer;
342   input_line_pointer = ilp;
343   return false;
344 }
345 
346 static bool
lex_match_string(const char * s)347 lex_match_string (const char *s)
348 {
349   char *p = input_line_pointer;
350   while (p != 0 && *p != '\t' && *p != ' ' && *p != '\0')
351     {
352       p++;
353     }
354 
355   size_t len = p - input_line_pointer;
356   if (len != strlen (s))
357     return false;
358 
359   if (0 == strncasecmp (s, input_line_pointer, len))
360     {
361       input_line_pointer = p;
362       return true;
363     }
364 
365   return false;
366 }
367 
368 /* Parse a register name.
369    WHICH is a ORwise combination of the registers which are accepted.
370    ~0 accepts all.
371    On success, REG will be filled with the index of the register which
372    was successfully scanned.
373 */
374 static bool
lex_reg_name(uint16_t which,int * reg)375 lex_reg_name (uint16_t which, int *reg)
376 {
377   char *p = input_line_pointer;
378 
379   if (p == 0)
380     return false;
381 
382   /* Scan (and ignore) the register prefix.  */
383   if (register_prefix)
384     {
385       int len = strlen (register_prefix);
386       if (0 == strncmp (register_prefix, p, len))
387         p += len;
388       else
389         return false;
390     }
391 
392   char *start_of_reg_name = p;
393 
394   while ((*p >= 'a' && *p <='z')
395          || (*p >= '0' && *p <= '9')
396          || (*p >= 'A' && *p <='Z'))
397     {
398       p++;
399     }
400 
401   size_t len = p - start_of_reg_name;
402 
403   if (len <= 0)
404     return false;
405 
406   int i;
407   for (i = 0; i < S12Z_N_REGISTERS; ++i)
408     {
409       gas_assert (registers[i].name);
410 
411       if (len == strlen (registers[i].name)
412 	  && 0 == strncasecmp (registers[i].name, start_of_reg_name, len))
413 	{
414 	  if ((0x1U << i) & which)
415 	    {
416 	      input_line_pointer = p;
417 	      *reg = i;
418 	      return true;
419 	    }
420 	}
421     }
422 
423   return false;
424 }
425 
426 static bool
lex_force_match(char x)427 lex_force_match (char x)
428 {
429   char *p = input_line_pointer;
430   if (*p != x)
431     {
432       as_bad (_("Expecting '%c'"), x);
433       return false;
434     }
435 
436   input_line_pointer++;
437   return true;
438 }
439 
440 static bool
lex_opr(uint8_t * buffer,int * n_bytes,expressionS * exp,bool immediate_ok)441 lex_opr (uint8_t *buffer, int *n_bytes, expressionS *exp,
442 	 bool immediate_ok)
443 {
444   char *ilp = input_line_pointer;
445   uint8_t *xb = buffer;
446   int reg;
447   long imm;
448   exp->X_op = O_absent;
449   *n_bytes = 0;
450   *xb = 0;
451   if (lex_imm_e4 (&imm))
452     {
453       if (!immediate_ok)
454 	{
455 	  as_bad (_("An immediate value in a source operand is inappropriate"));
456 	  return false;
457 	}
458       if (imm > 0)
459 	*xb = imm;
460       else
461 	*xb = 0;
462       *xb |= 0x70;
463       *n_bytes = 1;
464       return true;
465     }
466   else if (lex_reg_name (REG_BIT_Dn, &reg))
467     {
468       *xb = reg;
469       *xb |= 0xb8;
470       *n_bytes = 1;
471       return true;
472     }
473   else if (lex_match ('['))
474     {
475       if (lex_expression (exp))
476 	{
477 	  long c = exp->X_add_number;
478 	  if (lex_match (','))
479 	    {
480 	      if (lex_reg_name (REG_BIT_XYSP, &reg))
481 		{
482 		  int i;
483 		  if (c <= 255 && c >= -256)
484 		    {
485 		      *n_bytes = 2;
486 		      *xb |= 0xc4;
487 		    }
488 		  else
489 		    {
490 		      *n_bytes = 4;
491 		      *xb |= 0xc6;
492 		    }
493 		  *xb |= (reg - REG_X) << 4;
494 
495 		  if (c < 0)
496 		    *xb |= 0x01;
497 		  for (i = 1; i < *n_bytes ; ++i)
498 		    {
499 		      buffer[i] = c >> (8 * (*n_bytes - i - 1));
500 		    }
501 		}
502 	      else
503 		{
504 		  as_bad (_("Bad operand for constant offset"));
505 		  goto fail;
506 		}
507 	    }
508 	  else
509 	    {
510 	      *xb = 0xfe;
511 	      *n_bytes = 4;
512 	      buffer[1] = c >> 16;
513 	      buffer[2] = c >> 8;
514 	      buffer[3] = c;
515 	    }
516 	}
517       else if (lex_reg_name (REG_BIT_Dn, &reg))
518 	{
519 	  if (!lex_force_match (','))
520 	    goto fail;
521 
522 	  int reg2;
523 	  if (lex_reg_name (REG_BIT_XY, &reg2))
524 	    {
525 	      *n_bytes = 1;
526 	      *xb = reg;
527 	      *xb |= (reg2 - REG_X) << 4;
528 	      *xb |= 0xc8;
529 	    }
530 	  else
531 	    {
532 	      as_bad (_("Invalid operand for register offset"));
533 	      goto fail;
534 	    }
535 	}
536       else
537 	{
538 	  goto fail;
539 	}
540       if (!lex_force_match (']'))
541 	goto fail;
542       return true;
543     }
544   else if (lex_match ('('))
545     {
546       long c;
547       if (lex_constant (&c))
548 	{
549 	  if (!lex_force_match (','))
550 	    goto fail;
551 	  int reg2;
552 	  if (lex_reg_name (REG_BIT_XYSP, &reg2))
553 	    {
554 	      if (reg2 != REG_P && c >= 0 && c <= 15)
555 		{
556 		  *n_bytes = 1;
557 		  *xb = 0x40;
558 		  *xb |= (reg2 - REG_X) << 4;
559 		  *xb |= c;
560 		}
561 	      else if (c >= -256 && c <= 255)
562 		{
563 		  *n_bytes = 2;
564 		  *xb = 0xc0;
565 		  *xb |= (reg2 - REG_X) << 4;
566 		  if (c < 0)
567 		    *xb |= 0x01;
568 		  buffer[1] = c;
569 		}
570 	      else
571 		{
572 		  *n_bytes = 4;
573 		  *xb = 0xc2;
574 		  *xb |= (reg2 - REG_X) << 4;
575 		  buffer[1] = c >> 16;
576 		  buffer[2] = c >> 8;
577 		  buffer[3] = c;
578 		}
579 	    }
580 	  else if (lex_reg_name (REG_BIT_Dn, &reg2))
581 	    {
582 	      if (c >= -1 * (long) (0x1u << 17)
583 		  &&
584 		  c < (long) (0x1u << 17) - 1)
585 		{
586 		  *n_bytes = 3;
587 		  *xb = 0x80;
588 		  *xb |= reg2;
589 		  *xb |= ((c >> 16) & 0x03) << 4;
590 		  buffer[1] = c >> 8;
591 		  buffer[2] = c;
592 		}
593 	      else
594 		{
595 		  *n_bytes = 4;
596 		  *xb = 0xe8;
597 		  *xb |= reg2;
598 		  buffer[1] = c >> 16;
599 		  buffer[2] = c >> 8;
600 		  buffer[3] = c;
601 		}
602 	    }
603 	  else
604 	    {
605 	      as_bad (_("Bad operand for constant offset"));
606 	      goto fail;
607 	    }
608 	}
609       else if (lex_reg_name (REG_BIT_Dn, &reg))
610 	{
611 	  if (lex_match (','))
612 	    {
613 	      int reg2;
614 	      if (lex_reg_name (REG_BIT_XYS, &reg2))
615 		{
616 		  *n_bytes = 1;
617 		  *xb = 0x88;
618 		  *xb |= (reg2 - REG_X) << 4;
619 		  *xb |= reg;
620 		}
621 	      else
622 		{
623 		  as_bad (_("Invalid operand for register offset"));
624 		  goto fail;
625 		}
626 	    }
627 	  else
628 	    {
629 	      goto fail;
630 	    }
631 	}
632       else if (lex_reg_name (REG_BIT_XYS, &reg))
633 	{
634 	  if (lex_match ('-'))
635 	    {
636 	      if (reg == REG_S)
637 		{
638 		  as_bad (_("Invalid register for postdecrement operation"));
639 		  goto fail;
640 		}
641 	      *n_bytes = 1;
642 	      if (reg == REG_X)
643 		*xb = 0xc7;
644 	      else if (reg == REG_Y)
645 		*xb = 0xd7;
646 	    }
647 	  else if (lex_match ('+'))
648 	    {
649 	      *n_bytes = 1;
650 	      if (reg == REG_X)
651 		*xb = 0xe7;
652 	      else if (reg == REG_Y)
653 		*xb = 0xf7;
654 	      else if (reg == REG_S)
655 		*xb = 0xff;
656 	    }
657 	  else
658 	    {
659 	      goto fail;
660 	    }
661 	}
662       else if (lex_match ('+'))
663 	{
664 	  if (lex_reg_name (REG_BIT_XY, &reg))
665 	    {
666 	      *n_bytes = 1;
667 	      if (reg == REG_X)
668 		*xb = 0xe3;
669 	      else if (reg == REG_Y)
670 		*xb = 0xf3;
671 	    }
672 	  else
673 	    {
674 	      as_bad (_("Invalid register for preincrement operation"));
675 	      goto fail;
676 	    }
677 	}
678       else if (lex_match ('-'))
679 	{
680 	  if (lex_reg_name (REG_BIT_XYS, &reg))
681 	    {
682 	      *n_bytes = 1;
683 	      if (reg == REG_X)
684 		*xb = 0xc3;
685 	      else if (reg == REG_Y)
686 		*xb = 0xd3;
687 	      else if (reg == REG_S)
688 		*xb = 0xfb;
689 	    }
690 	  else
691 	    {
692 	      as_bad (_("Invalid register for predecrement operation"));
693 	      goto fail;
694 	    }
695 	}
696       else
697 	{
698 	  goto fail;
699 	}
700 
701       if (! lex_match (')'))
702 	goto fail;
703       return true;
704     }
705   else if (lex_expression (exp))
706     {
707       *xb = 0xfa;
708       *n_bytes = 4;
709       buffer[1] = 0;
710       buffer[2] = 0;
711       buffer[3] = 0;
712       if (exp->X_op == O_constant)
713 	{
714 	  valueT value = exp->X_add_number;
715 
716 	  if (value < (0x1U << 14))
717 	    {
718 	      *xb = 0x00;
719 	      *n_bytes = 2;
720 	      *xb |= value >> 8;
721 	      buffer[1] = value;
722 	    }
723 	  else if (value < (0x1U << 19))
724 	    {
725 	      *xb = 0xf8;
726 	      if (value & (0x1U << 17))
727 		*xb |= 0x04;
728 	      if (value & (0x1U << 16))
729 		*xb |= 0x01;
730 	      *n_bytes = 3;
731 	      buffer[1] = value >> 8;
732 	      buffer[2] = value;
733 	    }
734 	  else
735 	    {
736 	      *xb = 0xfa;
737 	      *n_bytes = 4;
738 	      buffer[1] = value >> 16;
739 	      buffer[2] = value >> 8;
740 	      buffer[3] = value;
741 	    }
742 	}
743       return true;
744     }
745 
746  fail:
747   fail_line_pointer = input_line_pointer;
748   input_line_pointer = ilp;
749   return false;
750 }
751 
752 static bool
lex_offset(long * val)753 lex_offset (long *val)
754 {
755   char *end = NULL;
756   char *p = input_line_pointer;
757 
758   if (*p++ != '*')
759     return false;
760 
761   if (*p != '+' && *p != '-')
762     return false;
763 
764   bool negative =  (*p == '-');
765   p++;
766 
767   errno = 0;
768   *val = s12z_strtol (p, &end);
769   if (errno == 0)
770     {
771       if (negative)
772 	*val *= -1;
773       input_line_pointer = end;
774       return true;
775     }
776 
777   return false;
778 }
779 
780 
781 
782 struct instruction;
783 
784 typedef bool (*parse_operand_func) (const struct instruction *);
785 
786 struct instruction
787 {
788   const char *name;
789 
790   /* The "page" to which the instruction belongs.
791      This is also only a hint.  Some instructions might have modes in both
792      pages... */
793   char page;
794 
795   /* This is a hint - and only a hint - about the opcode of the instruction.
796      The parse_operand_func is free to ignore it.
797   */
798   uint8_t opc;
799 
800   parse_operand_func parse_operands;
801 
802   /* Some instructions can be encoded with a different opcode */
803   uint8_t alt_opc;
804 };
805 
806 static bool
no_operands(const struct instruction * insn)807 no_operands (const struct instruction *insn)
808 {
809   if (*input_line_pointer != '\0')
810     {
811       as_bad (_("Garbage at end of instruction"));
812       return false;
813     }
814 
815   char *f = s12z_new_insn (insn->page);
816   if (insn->page == 2)
817     number_to_chars_bigendian (f++, PAGE2_PREBYTE, 1);
818 
819   number_to_chars_bigendian (f++, insn->opc, 1);
820 
821   return true;
822 }
823 
824 
825 static void
emit_reloc(expressionS * exp,char * f,int size,enum bfd_reloc_code_real reloc)826 emit_reloc (expressionS *exp, char *f, int size, enum bfd_reloc_code_real reloc)
827 {
828   if (exp->X_op != O_absent && exp->X_op != O_constant)
829     {
830       fixS *fix = fix_new_exp (frag_now,
831 			       f - frag_now->fr_literal,
832 			       size,
833 			       exp,
834 			       false,
835                                reloc);
836       /* Some third party tools seem to use the lower bits
837          of this addend for flags.   They don't get added
838          to the final location.   The purpose of these flags
839          is not known.  We simply set it to zero.  */
840       fix->fx_addnumber = 0x00;
841     }
842 }
843 
844 /* Emit the code for an OPR address mode operand */
845 static char *
emit_opr(char * f,const uint8_t * buffer,int n_bytes,expressionS * exp)846 emit_opr (char *f, const uint8_t *buffer, int n_bytes, expressionS *exp)
847 {
848   int i;
849   number_to_chars_bigendian (f++, buffer[0], 1);
850 
851   emit_reloc (exp, f, 3, BFD_RELOC_S12Z_OPR);
852 
853   for (i = 1; i < n_bytes; ++i)
854     number_to_chars_bigendian (f++,  buffer[i], 1);
855 
856   return f;
857 }
858 
859 /* Emit the code for a 24 bit direct address operand */
860 static char *
emit_ext24(char * f,long v)861 emit_ext24 (char *f, long v)
862 {
863   number_to_chars_bigendian (f, v, 3);
864 
865   return f + 3;
866 }
867 
868 static bool
opr(const struct instruction * insn)869 opr (const struct instruction *insn)
870 {
871   uint8_t buffer[4];
872   int n_bytes;
873   expressionS exp;
874   if (lex_opr (buffer, &n_bytes, &exp, false))
875     {
876       /* Large constant direct values are more efficiently encoded as ext24 mode.
877 	 Otherwise a decision has to be deferred to a relax. */
878       if (exp.X_op == O_constant
879 	  && buffer[0] == 0xFA
880 	  && insn->alt_opc != 0)
881 	{
882 	  char *f = s12z_new_insn (4);
883 
884 	  /* I don't think there are any instances of page 2 opcodes in this case */
885 	  gas_assert (insn->page == 1);
886 
887 	  number_to_chars_bigendian (f++, insn->alt_opc, 1);
888 
889 	  emit_ext24 (f, exp.X_add_number);
890 	}
891       else
892 	{
893 	  char *f = s12z_new_insn (n_bytes + 1);
894 	  number_to_chars_bigendian (f++, insn->opc, 1);
895 
896 	  emit_opr (f, buffer, n_bytes, &exp);
897 	}
898       return true;
899     }
900 
901   return false;
902 }
903 
904 /* Parse a 15 bit offset, as an expression.
905    LONG_DISPLACEMENT will be set to true if the offset is wider than 7 bits.
906    */
907 static bool
lex_15_bit_offset(bool * long_displacement,expressionS * exp)908 lex_15_bit_offset (bool *long_displacement, expressionS *exp)
909 {
910   char *ilp = input_line_pointer;
911 
912   long val;
913   if (lex_offset (&val))
914     {
915       exp->X_op = O_absent;
916       exp->X_add_number = val;
917     }
918   else if (lex_expression (exp))
919     {
920       if (exp->X_op == O_constant)
921 	{
922 	  val = exp->X_add_number;
923 	}
924       else
925 	{
926 	  /* If a symbol was parsed we don't know the displacement.
927 	     We have to assume it is long, and relax it later if possible. */
928 	  *long_displacement = true;
929 	  return true;
930 	}
931     }
932   else
933     {
934       exp->X_op = O_absent;
935       goto fail;
936     }
937 
938   if (val > 0x3FFF || val < -0x4000)
939     {
940       as_fatal (_("Offset is outside of 15 bit range"));
941       return false;
942     }
943 
944   *long_displacement = (val > 63 || val < -64);
945 
946   return true;
947 
948  fail:
949   fail_line_pointer = input_line_pointer;
950   input_line_pointer = ilp;
951   return false;
952 }
953 
954 static void
emit_15_bit_offset(char * f,int where,expressionS * exp)955 emit_15_bit_offset (char *f, int where, expressionS *exp)
956 {
957   gas_assert (exp);
958   if (exp->X_op != O_absent && exp->X_op != O_constant)
959     {
960       exp->X_add_number += where;
961       fixS *fix = fix_new_exp (frag_now,
962 		   f - frag_now->fr_literal,
963 		   2,
964 		   exp,
965 		   true,
966 		   BFD_RELOC_16_PCREL);
967       fix->fx_addnumber = where - 2;
968     }
969   else
970     {
971       long val = exp->X_add_number;
972       bool long_displacement = (val > 63 || val < -64);
973       if (long_displacement)
974 	val |= 0x8000;
975       else
976 	val &= 0x7F;
977 
978       number_to_chars_bigendian (f++, val, long_displacement ? 2 : 1);
979     }
980 }
981 
982 static bool
rel(const struct instruction * insn)983 rel (const struct instruction *insn)
984 {
985   bool long_displacement;
986 
987   expressionS exp;
988   if (! lex_15_bit_offset (&long_displacement, &exp))
989     return false;
990 
991   char *f = s12z_new_insn (long_displacement ? 3 : 2);
992   number_to_chars_bigendian (f++, insn->opc, 1);
993   emit_15_bit_offset (f, 3, &exp);
994   return true;
995 }
996 
997 static bool
reg_inh(const struct instruction * insn)998 reg_inh (const struct instruction *insn)
999 {
1000   int reg;
1001   if (lex_reg_name (REG_BIT_Dn, &reg))
1002     {
1003       char *f = s12z_new_insn (insn->page);
1004       if (insn->page == 2)
1005 	number_to_chars_bigendian (f++, PAGE2_PREBYTE, 1);
1006 
1007       number_to_chars_bigendian (f++, insn->opc + reg, 1);
1008       return true;
1009     }
1010 
1011   return false;
1012 }
1013 
1014 
1015 /* Special case for CLR X and CLR Y */
1016 static bool
clr_xy(const struct instruction * insn ATTRIBUTE_UNUSED)1017 clr_xy (const struct instruction *insn ATTRIBUTE_UNUSED)
1018 {
1019   int reg;
1020   if (lex_reg_name (REG_BIT_XY, &reg))
1021     {
1022       char *f = s12z_new_insn (1);
1023       number_to_chars_bigendian (f, 0x9a + reg - REG_X, 1);
1024       return true;
1025     }
1026 
1027   return false;
1028 }
1029 
1030 /* Some instructions have a suffix like ".l", ".b", ".w" etc
1031    which indicates the size of the operands. */
1032 static int
size_from_suffix(const struct instruction * insn,int idx)1033 size_from_suffix  (const struct instruction *insn, int idx)
1034 {
1035   const char *dot = strchr (insn->name, '.');
1036 
1037   if (dot == NULL)
1038     return -3;
1039 
1040   int size = -2;
1041   switch (dot[1 + idx])
1042     {
1043     case 'b':
1044       size = 1;
1045       break;
1046     case 'w':
1047       size = 2;
1048       break;
1049     case 'p':
1050       size = 3;
1051       break;
1052     case 'l':
1053       size = 4;
1054       break;
1055     default:
1056       as_fatal (_("Bad size"));
1057     };
1058 
1059   return size;
1060 }
1061 
1062 static bool
mul_reg_reg_reg(const struct instruction * insn)1063 mul_reg_reg_reg (const struct instruction *insn)
1064 {
1065   char *ilp = input_line_pointer;
1066 
1067   int Dd;
1068   if (!lex_reg_name (REG_BIT_Dn, &Dd))
1069     goto fail;
1070 
1071   if (!lex_match (','))
1072     goto fail;
1073 
1074   int Dj;
1075   if (!lex_reg_name (REG_BIT_Dn, &Dj))
1076     goto fail;
1077 
1078   if (!lex_match (','))
1079     goto fail;
1080 
1081   int Dk;
1082   if (!lex_reg_name (REG_BIT_Dn, &Dk))
1083     goto fail;
1084 
1085   char *f = s12z_new_insn (insn->page + 1);
1086   if (insn->page == 2)
1087     number_to_chars_bigendian (f++, PAGE2_PREBYTE, 1);
1088 
1089   number_to_chars_bigendian (f++, insn->opc + Dd, 1);
1090   const char *dot = strchrnul (insn->name, '.');
1091   uint8_t mb ;
1092   switch (dot[-1])
1093     {
1094     case 's':
1095       mb = 0x80;
1096       break;
1097     case 'u':
1098       mb = 0x00;
1099       break;
1100     default:
1101       as_fatal (_("BAD MUL"));
1102       break;
1103     }
1104 
1105   mb |= Dj << 3;
1106   mb |= Dk;
1107 
1108   number_to_chars_bigendian (f++, mb, 1);
1109 
1110   return true;
1111 
1112  fail:
1113   fail_line_pointer = input_line_pointer;
1114   input_line_pointer = ilp;
1115   return false;
1116 }
1117 
1118 
1119 static bool
mul_reg_reg_imm(const struct instruction * insn)1120 mul_reg_reg_imm (const struct instruction *insn)
1121 {
1122   char *ilp = input_line_pointer;
1123 
1124   int Dd;
1125   if (!lex_reg_name (REG_BIT_Dn, &Dd))
1126     goto fail;
1127 
1128   if (!lex_match (','))
1129     goto fail;
1130 
1131   int Dj;
1132   if (!lex_reg_name (REG_BIT_Dn, &Dj))
1133     goto fail;
1134 
1135   if (!lex_match (','))
1136     goto fail;
1137 
1138   long imm;
1139   if (!lex_imm (&imm, NULL))
1140     goto fail;
1141 
1142 
1143   int size = size_from_suffix (insn, 0);
1144 
1145   char *f = s12z_new_insn (insn->page + 1 + size);
1146   if (insn->page == 2)
1147     number_to_chars_bigendian (f++, PAGE2_PREBYTE, 1);
1148 
1149   number_to_chars_bigendian (f++, insn->opc + Dd, 1);
1150   uint8_t mb = 0x44;
1151   const char *dot = strchrnul (insn->name, '.');
1152   switch (dot[-1])
1153     {
1154     case 's':
1155       mb |= 0x80;
1156       break;
1157     case 'u':
1158       mb |= 0x00;
1159       break;
1160     default:
1161       as_fatal (_("BAD MUL"));
1162       break;
1163     }
1164 
1165   mb |= Dj << 3;
1166   mb |= size  - 1;
1167 
1168   number_to_chars_bigendian (f++, mb, 1);
1169   number_to_chars_bigendian (f++, imm, size);
1170 
1171   return true;
1172 
1173  fail:
1174   fail_line_pointer = input_line_pointer;
1175   input_line_pointer = ilp;
1176   return false;
1177 }
1178 
1179 
1180 static bool
mul_reg_reg_opr(const struct instruction * insn)1181 mul_reg_reg_opr (const struct instruction *insn)
1182 {
1183   char *ilp = input_line_pointer;
1184 
1185   int Dd;
1186   if (!lex_reg_name (REG_BIT_Dn, &Dd))
1187     goto fail;
1188 
1189   if (!lex_match (','))
1190     goto fail;
1191 
1192   int Dj;
1193   if (!lex_reg_name (REG_BIT_Dn, &Dj))
1194     goto fail;
1195 
1196   if (!lex_match (','))
1197     goto fail;
1198 
1199   uint8_t buffer[4];
1200   int n_bytes;
1201   expressionS exp;
1202   if (!lex_opr (buffer, &n_bytes, &exp, true))
1203     goto fail;
1204 
1205   int size = size_from_suffix (insn, 0);
1206 
1207   char *f = s12z_new_insn (insn->page + 1 + n_bytes);
1208   if (insn->page == 2)
1209     number_to_chars_bigendian (f++, PAGE2_PREBYTE, 1);
1210 
1211   number_to_chars_bigendian (f++, insn->opc + Dd, 1);
1212   uint8_t mb = 0x40;
1213   const char *dot = strchrnul (insn->name, '.');
1214   switch (dot[-1])
1215     {
1216     case 's':
1217       mb |= 0x80;
1218       break;
1219     case 'u':
1220       mb |= 0x00;
1221       break;
1222     default:
1223       as_fatal (_("BAD MUL"));
1224       break;
1225     }
1226 
1227   mb |= Dj << 3;
1228   mb |= size  - 1;
1229 
1230   number_to_chars_bigendian (f++, mb, 1);
1231 
1232   emit_opr (f, buffer, n_bytes, &exp);
1233 
1234   return true;
1235 
1236  fail:
1237   fail_line_pointer = input_line_pointer;
1238   input_line_pointer = ilp;
1239   return false;
1240 }
1241 
1242 static bool
mul_reg_opr_opr(const struct instruction * insn)1243 mul_reg_opr_opr (const struct instruction *insn)
1244 {
1245   char *ilp = input_line_pointer;
1246 
1247   int Dd;
1248   if (!lex_reg_name (REG_BIT_Dn, &Dd))
1249     goto fail;
1250 
1251   if (!lex_match (','))
1252     goto fail;
1253 
1254   uint8_t buffer1[4];
1255   int n_bytes1;
1256   expressionS exp1;
1257   if (!lex_opr (buffer1, &n_bytes1, &exp1, false))
1258     goto fail;
1259 
1260   if (!lex_match (','))
1261     goto fail;
1262 
1263   uint8_t buffer2[4];
1264   int n_bytes2;
1265   expressionS exp2;
1266   if (!lex_opr (buffer2, &n_bytes2, &exp2, false))
1267     goto fail;
1268 
1269   int size1 = size_from_suffix (insn, 0);
1270   int size2 = size_from_suffix (insn, 1);
1271 
1272   char *f = s12z_new_insn (insn->page + 1 + n_bytes1 + n_bytes2);
1273   if (insn->page == 2)
1274     number_to_chars_bigendian (f++, PAGE2_PREBYTE, 1);
1275 
1276   number_to_chars_bigendian (f++, insn->opc + Dd, 1);
1277   uint8_t mb = 0x42;
1278   const char *dot = strchrnul (insn->name, '.');
1279   switch (dot[-1])
1280     {
1281     case 's':
1282       mb |= 0x80;
1283       break;
1284     case 'u':
1285       mb |= 0x00;
1286       break;
1287     default:
1288       as_fatal (_("BAD MUL"));
1289       break;
1290     }
1291 
1292   mb |= (size1  - 1) << 4;
1293   mb |= (size2  - 1) << 2;
1294   number_to_chars_bigendian (f++, mb, 1);
1295 
1296   f = emit_opr (f, buffer1, n_bytes1, &exp1);
1297   f = emit_opr (f, buffer2, n_bytes2, &exp2);
1298 
1299   return true;
1300 
1301  fail:
1302   fail_line_pointer = input_line_pointer;
1303   input_line_pointer = ilp;
1304   return false;
1305 }
1306 
1307 
1308 #define REG_BIT_GRP0				\
1309   ((0x1U << REG_D2) |				\
1310    (0x1U << REG_D3) |				\
1311    (0x1U << REG_CCH) |				\
1312    (0x1U << REG_CCL) |				\
1313    (0x1U << REG_D0) |				\
1314    (0x1U << REG_D1))
1315 
1316 #define REG_BIT_GRP1				\
1317   ((0x1U << REG_D4) |				\
1318    (0x1U << REG_D5) |				\
1319    (0x1U << REG_D6) |				\
1320    (0x1U << REG_D7) |				\
1321    (0x1U << REG_X) |				\
1322    (0x1U << REG_Y))
1323 
1324 static const uint8_t reg_map [] =
1325   {
1326     0x02,  /* D2 */
1327     0x01,  /* D3 */
1328     0x20,
1329     0x10,  /* D5 */
1330     0x08,  /* D0 */
1331     0x04,  /* D1 */
1332     0x08,  /* D6 */
1333     0x04,  /* D7 */
1334     0x02,
1335     0x01,  /* Y */
1336     0x00,
1337     0x00,
1338     0x20,  /* CCH */
1339     0x10,  /* CCL */
1340     0x00
1341   };
1342 
1343 static bool
lex_reg_list(uint16_t grp,uint16_t * reg_bits)1344 lex_reg_list (uint16_t grp, uint16_t *reg_bits)
1345 {
1346   if (lex_match (','))
1347     {
1348       int reg;
1349       if (!lex_reg_name (grp, &reg))
1350 	return false;
1351       *reg_bits |= 0x1u << reg;
1352       lex_reg_list (grp, reg_bits);
1353     }
1354 
1355   /* Empty list */
1356   return true;
1357 }
1358 
1359 static bool
psh_pull(const struct instruction * insn)1360 psh_pull (const struct instruction *insn)
1361 {
1362   uint8_t pb =
1363     (0 == strcmp ("pul", insn->name)) ? 0x80: 0x00;
1364 
1365   if (lex_match_string ("all16b"))
1366     {
1367       pb |= 0x40;
1368     }
1369   else if (lex_match_string ("all"))
1370     {
1371       /* Nothing to do */
1372     }
1373   else
1374     {
1375       int reg1;
1376       if (!lex_reg_name (REG_BIT_GRP1 | REG_BIT_GRP0, &reg1))
1377 	goto fail;
1378       uint16_t admitted_group = 0;
1379 
1380       if ((0x1U << reg1) & REG_BIT_GRP1)
1381 	admitted_group = REG_BIT_GRP1;
1382       else if ((0x1U << reg1) & REG_BIT_GRP0)
1383 	admitted_group = REG_BIT_GRP0;
1384 
1385       uint16_t reg_bits = 0x1 << reg1;
1386       if (!lex_reg_list (admitted_group, &reg_bits))
1387 	goto fail;
1388 
1389       if (reg_bits & REG_BIT_GRP1)
1390 	pb |= 0x40;
1391 
1392       int i;
1393       for (i = 0; i < 16; ++i)
1394 	{
1395 	  if (reg_bits & (0x1u << i))
1396 	    pb |= reg_map[i];
1397 	}
1398     }
1399 
1400   char *f = s12z_new_insn (2);
1401   number_to_chars_bigendian (f++, insn->opc, 1);
1402   number_to_chars_bigendian (f++, pb, 1);
1403   return true;
1404 
1405  fail:
1406   fail_line_pointer = input_line_pointer;
1407   return false;
1408 }
1409 
1410 
1411 static bool
tfr(const struct instruction * insn)1412 tfr (const struct instruction *insn)
1413 {
1414   int reg1;
1415   if (!lex_reg_name (~0, &reg1))
1416     goto fail;
1417 
1418   if (!lex_match (','))
1419     goto fail;
1420 
1421   int reg2;
1422   if (!lex_reg_name (~0, &reg2))
1423     goto fail;
1424 
1425   if ( ((0 == strcasecmp ("sex", insn->name))
1426         || (0 == strcasecmp ("zex", insn->name)))
1427        && (registers[reg2].bytes <= registers[reg1].bytes))
1428       as_warn (_("Source register for %s is no larger than the destination register"),
1429                insn->name);
1430   else if (reg1 == reg2)
1431     as_warn (_("The destination and source registers are identical"));
1432 
1433   char *f = s12z_new_insn (1 + insn->page);
1434   if (insn->page == 2)
1435     number_to_chars_bigendian (f++, PAGE2_PREBYTE, 1);
1436 
1437   number_to_chars_bigendian (f++, insn->opc, 1);
1438   number_to_chars_bigendian (f++, reg1 << 4 | reg2, 1);
1439 
1440   return true;
1441 
1442  fail:
1443   fail_line_pointer = input_line_pointer;
1444   return false;
1445 }
1446 
1447 static bool
imm8(const struct instruction * insn)1448 imm8 (const struct instruction *insn)
1449 {
1450   long imm;
1451   if (! lex_imm (&imm, NULL))
1452     return false;
1453   if (imm > 127 || imm < -128)
1454     {
1455       as_bad (_("Immediate value %ld is out of range for instruction %s"),
1456 	      imm, insn->name);
1457     }
1458 
1459   char *f = s12z_new_insn (2);
1460   number_to_chars_bigendian (f++, insn->opc, 1);
1461   number_to_chars_bigendian (f++, imm, 1);
1462 
1463   return true;
1464 }
1465 
1466 static bool
reg_imm(const struct instruction * insn,int allowed_reg)1467 reg_imm (const struct instruction *insn, int allowed_reg)
1468 {
1469   char *ilp = input_line_pointer;
1470   int reg;
1471   if (lex_reg_name (allowed_reg, &reg))
1472     {
1473       if (!lex_force_match (','))
1474 	goto fail;
1475       long imm;
1476       if (! lex_imm (&imm, NULL))
1477 	goto fail;
1478 
1479       short size = registers[reg].bytes;
1480       char *f = s12z_new_insn (insn->page + size);
1481       if (insn->page == 2)
1482 	number_to_chars_bigendian (f++, PAGE2_PREBYTE, 1);
1483 
1484       number_to_chars_bigendian (f++, insn->opc + reg, 1);
1485       number_to_chars_bigendian (f++, imm, size);
1486       return true;
1487     }
1488 
1489  fail:
1490   fail_line_pointer = input_line_pointer;
1491   input_line_pointer = ilp;
1492   return false;
1493 }
1494 
1495 
1496 static bool
regd_imm(const struct instruction * insn)1497 regd_imm (const struct instruction *insn)
1498 {
1499   return reg_imm (insn, REG_BIT_Dn);
1500 }
1501 
1502 static bool
regdxy_imm(const struct instruction * insn)1503 regdxy_imm (const struct instruction *insn)
1504 {
1505   return reg_imm (insn, REG_BIT_Dn | REG_BIT_XY);
1506 }
1507 
1508 
1509 static bool
regs_imm(const struct instruction * insn)1510 regs_imm (const struct instruction *insn)
1511 {
1512   return reg_imm (insn, 0x1U << REG_S);
1513 }
1514 
1515 static bool
trap_imm(const struct instruction * insn ATTRIBUTE_UNUSED)1516 trap_imm (const struct instruction *insn ATTRIBUTE_UNUSED)
1517 {
1518   long imm = -1;
1519   if (! lex_imm (&imm, NULL))
1520     goto fail;
1521 
1522   if (imm < 0x92 || imm > 0xFF ||
1523       (imm >= 0xA0 && imm <= 0xA7) ||
1524       (imm >= 0xB0 && imm <= 0xB7))
1525     {
1526       as_bad (_("trap value %ld is not valid"), imm);
1527       return false;
1528     }
1529   else
1530     {
1531       char *f = s12z_new_insn (2);
1532       number_to_chars_bigendian (f++, PAGE2_PREBYTE, 1);
1533       number_to_chars_bigendian (f++, imm & 0xFF, 1);
1534       return true;
1535     }
1536 
1537   return true;
1538 
1539  fail:
1540   fail_line_pointer = input_line_pointer;
1541   return false;
1542 }
1543 
1544 
1545 
1546 /* Special one byte instruction CMP X, Y */
1547 static bool
regx_regy(const struct instruction * insn)1548 regx_regy (const struct instruction *insn)
1549 {
1550   int reg;
1551   if (lex_reg_name (0x1U << REG_X, &reg))
1552     {
1553       if (lex_force_match (','))
1554 	{
1555 	  if (lex_reg_name (0x1U << REG_Y, &reg))
1556 	    {
1557 	      char *f = s12z_new_insn (1);
1558 	      number_to_chars_bigendian (f, insn->opc, 1);
1559 	      return true;
1560 	    }
1561 	}
1562     }
1563   return false;
1564 }
1565 
1566 /* Special one byte instruction SUB D6, X, Y */
1567 static bool
regd6_regx_regy(const struct instruction * insn)1568 regd6_regx_regy (const struct instruction *insn)
1569 {
1570   char *ilp = input_line_pointer;
1571   int reg;
1572   if (!lex_reg_name (0x1U << REG_D6, &reg))
1573     goto fail;
1574 
1575   if (!lex_match (','))
1576     goto fail;
1577 
1578   if (!lex_reg_name (0x1U << REG_X, &reg))
1579     goto fail;
1580 
1581   if (!lex_match (','))
1582     goto fail;
1583 
1584   if (!lex_reg_name (0x1U << REG_Y, &reg))
1585     goto fail;
1586 
1587   char *f = s12z_new_insn (1);
1588   number_to_chars_bigendian (f, insn->opc, 1);
1589   return true;
1590 
1591  fail:
1592   fail_line_pointer = input_line_pointer;
1593   input_line_pointer = ilp;
1594   return false;
1595 }
1596 
1597 /* Special one byte instruction SUB D6, Y, X */
1598 static bool
regd6_regy_regx(const struct instruction * insn)1599 regd6_regy_regx (const struct instruction *insn)
1600 {
1601   char *ilp = input_line_pointer;
1602   int reg;
1603   if (!lex_reg_name (0x1U << REG_D6, &reg))
1604     goto fail;
1605 
1606   if (!lex_match (','))
1607     goto fail;
1608 
1609   if (!lex_reg_name (0x1U << REG_Y, &reg))
1610     goto fail;
1611 
1612   if (!lex_match (','))
1613     goto fail;
1614 
1615   if (!lex_reg_name (0x1U << REG_X, &reg))
1616     goto fail;
1617 
1618   char *f = s12z_new_insn (1);
1619   number_to_chars_bigendian (f, insn->opc, 1);
1620   return true;
1621 
1622  fail:
1623   fail_line_pointer = input_line_pointer;
1624   input_line_pointer = ilp;
1625   return false;
1626 }
1627 
1628 static bool
reg_opr(const struct instruction * insn,int allowed_regs,bool immediate_ok)1629 reg_opr (const struct instruction *insn, int allowed_regs,
1630 	 bool immediate_ok)
1631 {
1632   char *ilp = input_line_pointer;
1633   int reg;
1634   if (lex_reg_name (allowed_regs, &reg))
1635     {
1636       if (!lex_force_match (','))
1637 	goto fail;
1638 
1639       uint8_t buffer[4];
1640       int n_bytes;
1641       expressionS exp;
1642       if (lex_opr (buffer, &n_bytes, &exp, immediate_ok))
1643 	{
1644 	  /* Large constant direct values are more efficiently encoded as ext24 mode.
1645 	     Otherwise a decision has to be deferred to a relax. */
1646 	  if (exp.X_op == O_constant
1647 	      && buffer[0] == 0xFA
1648 	      && insn->alt_opc != 0)
1649 	    {
1650 	      char *f = s12z_new_insn (4);
1651 
1652 	      /* I don't think there are any instances of page 2 opcodes in this case */
1653 	      gas_assert (insn->page == 1);
1654 
1655 	      number_to_chars_bigendian (f++, insn->alt_opc + reg, 1);
1656 
1657 	      emit_ext24 (f, exp.X_add_number);
1658 	    }
1659 	  else
1660 	    {
1661 	      char *f = s12z_new_insn (n_bytes + insn->page);
1662 
1663 	      if (insn->page == 2)
1664 		number_to_chars_bigendian (f++, PAGE2_PREBYTE, 1);
1665 
1666 	      number_to_chars_bigendian (f++, insn->opc + reg, 1);
1667 
1668 	      emit_opr (f, buffer, n_bytes, &exp);
1669 	    }
1670 
1671 	  return true;
1672 	}
1673     }
1674 
1675  fail:
1676   fail_line_pointer = input_line_pointer;
1677   input_line_pointer = ilp;
1678   return false;
1679 }
1680 
1681 
1682 static bool
regdxy_opr_dest(const struct instruction * insn)1683 regdxy_opr_dest (const struct instruction *insn)
1684 {
1685   return reg_opr (insn, REG_BIT_Dn | REG_BIT_XY, false);
1686 }
1687 
1688 static bool
regdxy_opr_src(const struct instruction * insn)1689 regdxy_opr_src (const struct instruction *insn)
1690 {
1691   return reg_opr (insn, REG_BIT_Dn | REG_BIT_XY, true);
1692 }
1693 
1694 
1695 static bool
regd_opr(const struct instruction * insn)1696 regd_opr (const struct instruction *insn)
1697 {
1698   return reg_opr (insn, REG_BIT_Dn, true);
1699 }
1700 
1701 
1702 /* OP0: S; OP1: destination OPR */
1703 static bool
regs_opr_dest(const struct instruction * insn)1704 regs_opr_dest (const struct instruction *insn)
1705 {
1706   return reg_opr (insn, 0x1U << REG_S, false);
1707 }
1708 
1709 /* OP0: S; OP1: source OPR */
1710 static bool
regs_opr_src(const struct instruction * insn)1711 regs_opr_src (const struct instruction *insn)
1712 {
1713   return reg_opr (insn, 0x1U << REG_S, true);
1714 }
1715 
1716 static bool
imm_opr(const struct instruction * insn)1717 imm_opr  (const struct instruction *insn)
1718 {
1719   char *ilp = input_line_pointer;
1720   long imm;
1721   expressionS exp0;
1722   int size = size_from_suffix (insn, 0);
1723   exp0.X_op = O_absent;
1724 
1725   /* Note:  The ternary expression below means that "MOV.x #symbol,
1726      mem-expr"  is accepted when x is a member of {'w', 'p', 'l'} but
1727      not when it is 'b'.
1728      The Freescale assembler accepts "MOV.b #symbol, mem-expr" but
1729      produces obviously incorrect code.    Since such an instruction
1730      would require an 8-bit reloc (which we don't have) and some
1731      non-optimal kludges in the OPR encoding, it seems sensible that
1732      such instructions should be rejected.  */
1733   if (!lex_imm (&imm, size > 1 ? &exp0 : NULL))
1734     goto fail;
1735 
1736   if (!lex_match (','))
1737     goto fail;
1738 
1739   uint8_t buffer[4];
1740   int n_bytes;
1741   expressionS exp1;
1742   if (!lex_opr (buffer, &n_bytes, &exp1, false))
1743     goto fail;
1744 
1745   char *f = s12z_new_insn (1 + n_bytes + size);
1746   number_to_chars_bigendian (f++, insn->opc, 1);
1747 
1748   emit_reloc (&exp0, f, size, size == 4 ? BFD_RELOC_32 : BFD_RELOC_S12Z_OPR);
1749 
1750   int i;
1751   for (i = 0; i < size; ++i)
1752     number_to_chars_bigendian (f++, imm >> (CHAR_BIT * (size - i - 1)), 1);
1753 
1754   emit_opr (f, buffer, n_bytes, &exp1);
1755 
1756   return true;
1757 
1758  fail:
1759   fail_line_pointer = input_line_pointer;
1760   input_line_pointer = ilp;
1761   return false;
1762 }
1763 
1764 static bool
opr_opr(const struct instruction * insn)1765 opr_opr  (const struct instruction *insn)
1766 {
1767   char *ilp = input_line_pointer;
1768 
1769   uint8_t buffer1[4];
1770   int n_bytes1;
1771   expressionS exp1;
1772   if (!lex_opr (buffer1, &n_bytes1, &exp1, false))
1773     goto fail;
1774 
1775 
1776   if (!lex_match (','))
1777     goto fail;
1778 
1779   uint8_t buffer2[4];
1780   int n_bytes2;
1781   expressionS exp2;
1782   if (!lex_opr (buffer2, &n_bytes2, &exp2, false))
1783     goto fail;
1784 
1785   char *f = s12z_new_insn (1 + n_bytes1 + n_bytes2);
1786   number_to_chars_bigendian (f++, insn->opc, 1);
1787 
1788   f = emit_opr (f, buffer1, n_bytes1, &exp1);
1789   f = emit_opr (f, buffer2, n_bytes2, &exp2);
1790 
1791   return true;
1792 
1793  fail:
1794   fail_line_pointer = input_line_pointer;
1795   input_line_pointer = ilp;
1796   return false;
1797 }
1798 
1799 static bool
reg67sxy_opr(const struct instruction * insn)1800 reg67sxy_opr  (const struct instruction *insn)
1801 {
1802   int reg;
1803   if (!lex_reg_name (REG_BIT_XYS | (0x1U << REG_D6) | (0x1U << REG_D7), &reg))
1804     return false;
1805 
1806   if (!lex_match (','))
1807     return false;
1808 
1809   uint8_t buffer[4];
1810   int n_bytes;
1811   expressionS exp;
1812   if (!lex_opr (buffer, &n_bytes, &exp, false))
1813     return false;
1814 
1815   char *f = s12z_new_insn (1 + n_bytes);
1816   number_to_chars_bigendian (f++, insn->opc + reg - REG_D6, 1);
1817   emit_opr (f, buffer, n_bytes, &exp);
1818 
1819   return true;
1820 }
1821 
1822 static bool
rotate(const struct instruction * insn,short dir)1823 rotate  (const struct instruction *insn, short dir)
1824 {
1825   uint8_t buffer[4];
1826   int n_bytes;
1827   expressionS exp;
1828   if (lex_opr (buffer, &n_bytes, &exp, false))
1829     {
1830       char *f = s12z_new_insn (n_bytes + 2);
1831       number_to_chars_bigendian (f++, insn->opc, 1);
1832       int size = size_from_suffix (insn, 0);
1833       if (size < 0)
1834 	size = 1;
1835       uint8_t sb = 0x24;
1836       sb |= size - 1;
1837       if (dir)
1838 	sb |= 0x40;
1839       number_to_chars_bigendian (f++, sb, 1);
1840       emit_opr (f, buffer, n_bytes, &exp);
1841 
1842       return true;
1843     }
1844 
1845   return false;
1846 }
1847 
1848 static bool
rol(const struct instruction * insn)1849 rol  (const struct instruction *insn)
1850 {
1851   return rotate (insn, 1);
1852 }
1853 
1854 static bool
ror(const struct instruction * insn)1855 ror  (const struct instruction *insn)
1856 {
1857   return rotate (insn, 0);
1858 }
1859 
1860 
1861 /* Shift instruction with a register operand and an immediate #1 or #2
1862    left = 1; right = 0;
1863    logical = 0; arithmetic = 1;
1864 */
1865 static bool
lex_shift_reg_imm1(const struct instruction * insn,short type,short dir)1866 lex_shift_reg_imm1  (const struct instruction *insn, short type, short dir)
1867 {
1868   /*
1869     This function is highly unusual and a bit wierd!
1870     It first matches the input against a register {d0, d1, ... d7} followed by an immediate
1871     {#1, #2}.
1872     Then, it rewinds the input and parses it again as a OPR.
1873   */
1874   char *ilp = input_line_pointer;
1875 
1876   int Dd;
1877   if (!lex_reg_name (REG_BIT_Dn, &Dd))
1878     {
1879       goto fail;
1880     }
1881 
1882   if (!lex_match (','))
1883     goto fail;
1884 
1885   long imm = -1;
1886   if (!lex_imm (&imm, NULL))
1887     goto fail;
1888 
1889   if (imm != 1 && imm != 2)
1890     goto fail;
1891   input_line_pointer = ilp;
1892 
1893   /* Now parse the first operand again */
1894 
1895   uint8_t buffer[4];
1896   int n_bytes;
1897 
1898   expressionS exp;
1899   if (!lex_opr (buffer, &n_bytes, &exp, false))
1900     goto fail;
1901 
1902   gas_assert (n_bytes == 1);
1903 
1904   uint8_t sb = 0x34;
1905   sb |= dir << 6;
1906   sb |= type << 7;
1907   if (imm == 2)
1908     sb |= 0x08;
1909 
1910   char *f = s12z_new_insn (3);
1911   number_to_chars_bigendian (f++, insn->opc, 1);
1912   number_to_chars_bigendian (f++, sb, 1);
1913   emit_opr (f, buffer, n_bytes, &exp);
1914 
1915   return true;
1916 
1917  fail:
1918   fail_line_pointer = input_line_pointer;
1919   input_line_pointer = ilp;
1920   return false;
1921 }
1922 
1923 /* Shift instruction with a register operand.
1924    left = 1; right = 0;
1925    logical = 0; arithmetic = 1; */
1926 static bool
lex_shift_reg(const struct instruction * insn,short type,short dir)1927 lex_shift_reg  (const struct instruction *insn, short type, short dir)
1928 {
1929   int Dd, Ds, Dn;
1930   if (!lex_reg_name (REG_BIT_Dn, &Dd))
1931     {
1932       goto fail;
1933     }
1934 
1935   if (!lex_match (','))
1936     goto fail;
1937 
1938   if (!lex_reg_name (REG_BIT_Dn, &Ds))
1939     {
1940       goto fail;
1941     }
1942 
1943   if (!lex_match (','))
1944     goto fail;
1945 
1946   uint8_t sb = 0x10;
1947   sb |= Ds;
1948   sb |= dir << 6;
1949   sb |= type << 7;
1950   long imm;
1951   if (lex_reg_name (REG_BIT_Dn, &Dn))
1952     {
1953       char *f = s12z_new_insn (3);
1954       number_to_chars_bigendian (f++, insn->opc | Dd, 1);
1955       number_to_chars_bigendian (f++, sb, 1);
1956       uint8_t xb = 0xb8;
1957       xb |= Dn;
1958       number_to_chars_bigendian (f++, xb, 1);
1959 
1960       return true;
1961     }
1962   else if (lex_imm (&imm, NULL))
1963     {
1964       if (imm < 0 || imm > 31)
1965 	{
1966 	  as_bad (_("Shift value should be in the range [0,31]"));
1967 	  goto fail;
1968 	}
1969 
1970       int n_bytes = 3;
1971       if (imm == 1 || imm == 2)
1972 	{
1973 	  n_bytes = 2;
1974 	  sb &= ~0x10;
1975 	}
1976       else
1977 	{
1978 	  sb |= (imm & 0x01) << 3;
1979 	}
1980 
1981       char *f = s12z_new_insn (n_bytes);
1982       number_to_chars_bigendian (f++, insn->opc | Dd, 1);
1983       number_to_chars_bigendian (f++, sb, 1);
1984       if (n_bytes > 2)
1985 	{
1986 	  uint8_t xb = 0x70;
1987 	  xb |= imm >> 1;
1988 	  number_to_chars_bigendian (f++, xb, 1);
1989 	}
1990 
1991       return true;
1992     }
1993 
1994  fail:
1995   fail_line_pointer = input_line_pointer;
1996   return false;
1997 }
1998 
1999 static void
impute_shift_dir_and_type(const struct instruction * insn,short * type,short * dir)2000 impute_shift_dir_and_type (const struct instruction *insn, short *type, short *dir)
2001 {
2002   *dir = -1;
2003   *type = -1;
2004   switch (insn->name[0])
2005     {
2006     case 'l':
2007       *type = 0;
2008       break;
2009     case 'a':
2010       *type = 1;
2011       break;
2012     default:
2013       as_fatal (_("Bad shift mode"));
2014       break;
2015     }
2016 
2017   switch (insn->name[2])
2018     {
2019     case 'l':
2020       *dir = 1;
2021       break;
2022     case 'r':
2023       *dir = 0;
2024       break;
2025     default:
2026       as_fatal (_("Bad shift *direction"));
2027       break;
2028     }
2029 }
2030 
2031 /* Shift instruction with a OPR operand */
2032 static bool
shift_two_operand(const struct instruction * insn)2033 shift_two_operand  (const struct instruction *insn)
2034 {
2035   uint8_t sb = 0x34;
2036   char *ilp = input_line_pointer;
2037 
2038   short dir = -1;
2039   short type = -1;
2040   impute_shift_dir_and_type (insn, &type, &dir);
2041   sb |= dir << 6;
2042   sb |= type << 7;
2043 
2044   int size = size_from_suffix (insn, 0);
2045   sb |= size - 1;
2046 
2047   uint8_t buffer[4];
2048   int n_opr_bytes;
2049   expressionS exp;
2050   if (!lex_opr (buffer, &n_opr_bytes, &exp, false))
2051     goto fail;
2052 
2053   if (!lex_match (','))
2054     goto fail;
2055 
2056   long imm = -1;
2057   if (!lex_imm (&imm, NULL))
2058     goto fail;
2059 
2060   if (imm != 1 && imm != 2)
2061     goto fail;
2062 
2063   if (imm == 2)
2064     sb |= 0x08;
2065 
2066   char *f = s12z_new_insn (2 + n_opr_bytes);
2067   number_to_chars_bigendian (f++, insn->opc, 1);
2068   number_to_chars_bigendian (f++, sb, 1);
2069   emit_opr (f, buffer, n_opr_bytes, &exp);
2070 
2071   return true;
2072 
2073  fail:
2074   fail_line_pointer = input_line_pointer;
2075   input_line_pointer = ilp;
2076   return false;
2077 }
2078 
2079 /* Shift instruction with a OPR operand */
2080 static bool
shift_opr_imm(const struct instruction * insn)2081 shift_opr_imm  (const struct instruction *insn)
2082 {
2083   char *ilp = input_line_pointer;
2084 
2085   short dir = -1;
2086   short type = -1;
2087   impute_shift_dir_and_type (insn, &type, &dir);
2088 
2089   int Dd = 0;
2090   if (!lex_reg_name (REG_BIT_Dn, &Dd))
2091     goto fail;
2092 
2093   if (!lex_match (','))
2094     goto fail;
2095 
2096   int n_bytes = 2;
2097 
2098   uint8_t buffer1[4];
2099   int n_opr_bytes1;
2100 
2101   expressionS exp1;
2102   if (!lex_opr (buffer1, &n_opr_bytes1, &exp1, false))
2103     goto fail;
2104 
2105   n_bytes += n_opr_bytes1;
2106   if (!lex_match (','))
2107     goto fail;
2108 
2109   uint8_t buffer2[4];
2110   int n_opr_bytes2 = 0;
2111   expressionS exp2;
2112   long imm;
2113   bool immediate = false;
2114   if (lex_imm (&imm, NULL))
2115     {
2116       immediate = true;
2117     }
2118   else if (!lex_opr (buffer2, &n_opr_bytes2, &exp2, false))
2119     goto fail;
2120 
2121   uint8_t sb = 0x20;
2122 
2123   int size = size_from_suffix (insn, 0);
2124 
2125   if (size != -1)
2126     sb |= size - 1;
2127 
2128   sb |= dir << 6;
2129   sb |= type << 7;
2130 
2131   if (immediate)
2132     {
2133       if (imm == 2 || imm == 1)
2134 	{
2135 	  if (imm == 2)
2136 	    sb |= 0x08;
2137 	}
2138       else
2139 	{
2140 	  n_bytes++;
2141 	  sb |= 0x10;
2142 	  if (imm % 2)
2143 	    sb |= 0x08;
2144 	}
2145     }
2146   else
2147     {
2148       n_bytes += n_opr_bytes2;
2149       sb |= 0x10;
2150     }
2151 
2152   char *f = s12z_new_insn (n_bytes);
2153   number_to_chars_bigendian (f++, insn->opc | Dd, 1);
2154   number_to_chars_bigendian (f++, sb, 1);
2155   f = emit_opr (f, buffer1, n_opr_bytes1, &exp1);
2156   if (immediate)
2157     {
2158       if (imm != 1 && imm != 2)
2159 	{
2160 	  number_to_chars_bigendian (f++, 0x70 | (imm >> 1), 1);
2161 	}
2162     }
2163   else
2164     {
2165       f = emit_opr (f, buffer2, n_opr_bytes2, &exp2);
2166     }
2167 
2168   return true;
2169 
2170  fail:
2171   fail_line_pointer = input_line_pointer;
2172   input_line_pointer = ilp;
2173   return false;
2174 }
2175 
2176 /* Shift instruction with a register operand */
2177 static bool
shift_reg(const struct instruction * insn)2178 shift_reg  (const struct instruction *insn)
2179 {
2180   short dir = -1;
2181   short type = -1;
2182   impute_shift_dir_and_type (insn, &type, &dir);
2183 
2184   if (lex_shift_reg_imm1 (insn, type, dir))
2185     return true;
2186 
2187   return lex_shift_reg (insn, type, dir);
2188 }
2189 
2190 static bool
bm_regd_imm(const struct instruction * insn)2191 bm_regd_imm  (const struct instruction *insn)
2192 {
2193   char *ilp = input_line_pointer;
2194   int Di = 0;
2195   if (!lex_reg_name (REG_BIT_Dn, &Di))
2196     goto fail;
2197 
2198   if (!lex_match (','))
2199     goto fail;
2200 
2201   long imm;
2202   if (!lex_imm (&imm, NULL))
2203     goto fail;
2204 
2205 
2206   uint8_t bm = imm << 3;
2207   bm |= Di;
2208 
2209   char *f = s12z_new_insn (2);
2210   number_to_chars_bigendian (f++, insn->opc, 1);
2211   number_to_chars_bigendian (f++, bm, 1);
2212 
2213   return true;
2214 
2215  fail:
2216   fail_line_pointer = input_line_pointer;
2217   input_line_pointer = ilp;
2218   return false;
2219 }
2220 
2221 static bool
bm_opr_reg(const struct instruction * insn)2222 bm_opr_reg  (const struct instruction *insn)
2223 {
2224   char *ilp = input_line_pointer;
2225 
2226   uint8_t buffer[4];
2227   int n_opr_bytes;
2228 
2229   expressionS exp;
2230   if (!lex_opr (buffer, &n_opr_bytes,  &exp, false))
2231     goto fail;
2232 
2233   if (!lex_match (','))
2234     goto fail;
2235 
2236   int Dn = 0;
2237   if (!lex_reg_name (REG_BIT_Dn, &Dn))
2238     goto fail;
2239 
2240   uint8_t bm = Dn << 4;
2241   int size = size_from_suffix (insn, 0);
2242   bm |= (size - 1) << 2;
2243   bm |= 0x81;
2244 
2245   char *f = s12z_new_insn (2 + n_opr_bytes);
2246   number_to_chars_bigendian (f++, insn->opc, 1);
2247   number_to_chars_bigendian (f++, bm, 1);
2248 
2249   emit_opr (f, buffer, n_opr_bytes, &exp);
2250 
2251   return true;
2252 
2253  fail:
2254   fail_line_pointer = input_line_pointer;
2255   input_line_pointer = ilp;
2256   return false;
2257 }
2258 
2259 
2260 static bool
bm_opr_imm(const struct instruction * insn)2261 bm_opr_imm  (const struct instruction *insn)
2262 {
2263   char *ilp = input_line_pointer;
2264 
2265   uint8_t buffer[4];
2266   int n_opr_bytes;
2267 
2268   expressionS exp;
2269   if (!lex_opr (buffer, &n_opr_bytes, &exp, false))
2270     goto fail;
2271 
2272   if (!lex_match (','))
2273     goto fail;
2274 
2275 
2276   long imm;
2277   if (!lex_imm (&imm, NULL))
2278     goto fail;
2279 
2280   int size = size_from_suffix (insn, 0);
2281 
2282   if (imm < 0 || imm >= size * 8)
2283     {
2284       as_bad (_("Immediate operand %ld is inappropriate for size of instruction"), imm);
2285       goto fail;
2286     }
2287 
2288   uint8_t bm = 0x80;
2289   if (size == 2)
2290     bm |= 0x02;
2291   else if (size == 4)
2292     bm |= 0x08;
2293   bm |= (imm & 0x07) << 4;
2294   bm |= (imm >> 3);
2295 
2296 
2297   char *f = s12z_new_insn (2 + n_opr_bytes);
2298   number_to_chars_bigendian (f++, insn->opc, 1);
2299   number_to_chars_bigendian (f++, bm, 1);
2300   emit_opr (f, buffer, n_opr_bytes, &exp);
2301 
2302   return true;
2303 
2304  fail:
2305   fail_line_pointer = input_line_pointer;
2306   input_line_pointer = ilp;
2307   return false;
2308 }
2309 
2310 
2311 static bool
bm_regd_reg(const struct instruction * insn)2312 bm_regd_reg  (const struct instruction *insn)
2313 {
2314   char *ilp = input_line_pointer;
2315   int Di = 0;
2316   if (!lex_reg_name (REG_BIT_Dn, &Di))
2317     goto fail;
2318 
2319   if (!lex_match (','))
2320     goto fail;
2321 
2322   int Dn = 0;
2323   if (!lex_reg_name (REG_BIT_Dn, &Dn))
2324     goto fail;
2325 
2326   uint8_t bm = Dn << 4;
2327   bm |= 0x81;
2328 
2329   uint8_t xb = Di | 0xb8;
2330 
2331   char *f = s12z_new_insn (3);
2332   number_to_chars_bigendian (f++, insn->opc, 1);
2333   number_to_chars_bigendian (f++, bm, 1);
2334   number_to_chars_bigendian (f++, xb, 1);
2335 
2336   return true;
2337 
2338  fail:
2339   fail_line_pointer = input_line_pointer;
2340   input_line_pointer = ilp;
2341   return false;
2342 }
2343 
2344 
2345 
2346 
2347 
2348 static bool
bf_reg_opr_imm(const struct instruction * insn,short ie)2349 bf_reg_opr_imm  (const struct instruction *insn, short ie)
2350 {
2351   char *ilp = input_line_pointer;
2352   int Dd = 0;
2353   if (!lex_reg_name (REG_BIT_Dn, &Dd))
2354     goto fail;
2355 
2356   if (!lex_match (','))
2357     goto fail;
2358 
2359   uint8_t buffer[4];
2360   int n_bytes;
2361 
2362   expressionS exp;
2363   if (!lex_opr (buffer, &n_bytes, &exp, false))
2364     goto fail;
2365 
2366   if (!lex_match (','))
2367     goto fail;
2368 
2369   long width;
2370   if (!lex_imm (&width, NULL))
2371     goto fail;
2372 
2373   if (width < 0 || width > 31)
2374     {
2375       as_bad (_("Invalid width value for %s"), insn->name);
2376       goto fail;
2377     }
2378 
2379   if (!lex_match (':'))
2380     goto fail;
2381 
2382   long offset;
2383   if (!lex_constant (&offset))
2384     goto fail;
2385 
2386   if (offset < 0 || offset > 31)
2387     {
2388       as_bad (_("Invalid offset value for %s"), insn->name);
2389       goto fail;
2390     }
2391 
2392   uint8_t i1 = width << 5;
2393   i1 |= offset;
2394 
2395   int size = size_from_suffix (insn, 0);
2396   uint8_t bb = ie ? 0x80 : 0x00;
2397   bb |= 0x60;
2398   bb |= (size - 1) << 2;
2399   bb |= width >> 3;
2400 
2401   char *f = s12z_new_insn (4 + n_bytes);
2402   number_to_chars_bigendian (f++, PAGE2_PREBYTE, 1);
2403   number_to_chars_bigendian (f++, 0x08 | Dd, 1);
2404   number_to_chars_bigendian (f++, bb, 1);
2405   number_to_chars_bigendian (f++, i1, 1);
2406 
2407   emit_opr (f, buffer, n_bytes, &exp);
2408 
2409   return true;
2410 
2411  fail:
2412   fail_line_pointer = input_line_pointer;
2413   input_line_pointer = ilp;
2414   return false;
2415 }
2416 
2417 
2418 static bool
bf_opr_reg_imm(const struct instruction * insn,short ie)2419 bf_opr_reg_imm  (const struct instruction *insn, short ie)
2420 {
2421   char *ilp = input_line_pointer;
2422   uint8_t buffer[4];
2423   int n_bytes;
2424   expressionS exp;
2425   if (!lex_opr (buffer, &n_bytes, &exp, false))
2426     goto fail;
2427 
2428   if (!lex_match (','))
2429     goto fail;
2430 
2431   int Ds = 0;
2432   if (!lex_reg_name (REG_BIT_Dn, &Ds))
2433     goto fail;
2434 
2435   if (!lex_match (','))
2436     goto fail;
2437 
2438   long width;
2439   if (!lex_imm (&width, NULL))
2440     goto fail;
2441 
2442   if (width < 0 || width > 31)
2443     {
2444       as_bad (_("Invalid width value for %s"), insn->name);
2445       goto fail;
2446     }
2447 
2448   if (!lex_match (':'))
2449     goto fail;
2450 
2451   long offset;
2452   if (!lex_constant (&offset))
2453     goto fail;
2454 
2455   if (offset < 0 || offset > 31)
2456     {
2457       as_bad (_("Invalid offset value for %s"), insn->name);
2458       goto fail;
2459     }
2460 
2461   uint8_t i1 = width << 5;
2462   i1 |= offset;
2463 
2464   int size = size_from_suffix (insn, 0);
2465   uint8_t bb = ie ? 0x80 : 0x00;
2466   bb |= 0x70;
2467   bb |= (size - 1) << 2;
2468   bb |= width >> 3;
2469 
2470   char *f = s12z_new_insn (4 + n_bytes);
2471   number_to_chars_bigendian (f++, PAGE2_PREBYTE, 1);
2472   number_to_chars_bigendian (f++, 0x08 | Ds, 1);
2473   number_to_chars_bigendian (f++, bb, 1);
2474   number_to_chars_bigendian (f++, i1, 1);
2475 
2476   emit_opr (f, buffer, n_bytes, &exp);
2477 
2478   return true;
2479 
2480  fail:
2481   fail_line_pointer = input_line_pointer;
2482   input_line_pointer = ilp;
2483   return false;
2484 }
2485 
2486 
2487 
2488 static bool
bf_reg_reg_imm(const struct instruction * insn,short ie)2489 bf_reg_reg_imm  (const struct instruction *insn, short ie)
2490 {
2491   char *ilp = input_line_pointer;
2492   int Dd = 0;
2493   if (!lex_reg_name (REG_BIT_Dn, &Dd))
2494     goto fail;
2495 
2496   if (!lex_match (','))
2497     goto fail;
2498 
2499   int Ds = 0;
2500   if (!lex_reg_name (REG_BIT_Dn, &Ds))
2501     goto fail;
2502 
2503   if (!lex_match (','))
2504     goto fail;
2505 
2506   long width;
2507   if (!lex_imm (&width, NULL))
2508     goto fail;
2509 
2510   if (width < 0 || width > 31)
2511     {
2512       as_bad (_("Invalid width value for %s"), insn->name);
2513       goto fail;
2514     }
2515 
2516   if (!lex_match (':'))
2517     goto fail;
2518 
2519   long offset;
2520   if (!lex_constant (&offset))
2521     goto fail;
2522 
2523   if (offset < 0 || offset > 31)
2524     {
2525       as_bad (_("Invalid offset value for %s"), insn->name);
2526       goto fail;
2527     }
2528 
2529   uint8_t bb = ie ? 0x80 : 0x00;
2530   bb |= 0x20;
2531   bb |= Ds << 2;
2532   bb |= width >> 3;
2533 
2534   uint8_t i1 = width << 5;
2535   i1 |= offset;
2536 
2537   char *f = s12z_new_insn (4);
2538   number_to_chars_bigendian (f++, PAGE2_PREBYTE, 1);
2539   number_to_chars_bigendian (f++, 0x08 | Dd, 1);
2540   number_to_chars_bigendian (f++, bb, 1);
2541   number_to_chars_bigendian (f++, i1, 1);
2542 
2543   return true;
2544 
2545  fail:
2546   fail_line_pointer = input_line_pointer;
2547   input_line_pointer = ilp;
2548   return false;
2549 }
2550 
2551 static bool
bf_reg_reg_reg(const struct instruction * insn ATTRIBUTE_UNUSED,short ie)2552 bf_reg_reg_reg  (const struct instruction *insn ATTRIBUTE_UNUSED, short ie)
2553 {
2554   char *ilp = input_line_pointer;
2555   int Dd = 0;
2556   if (!lex_reg_name (REG_BIT_Dn, &Dd))
2557     goto fail;
2558 
2559   if (!lex_match (','))
2560     goto fail;
2561 
2562   int Ds = 0;
2563   if (!lex_reg_name (REG_BIT_Dn, &Ds))
2564     goto fail;
2565 
2566   if (!lex_match (','))
2567     goto fail;
2568 
2569   int Dp = 0;
2570   if (!lex_reg_name  ((0x01u << REG_D2) |
2571 		      (0x01u << REG_D3) |
2572 		      (0x01u << REG_D4) |
2573 		      (0x01u << REG_D5),
2574 		      &Dp))
2575     goto fail;
2576 
2577   uint8_t bb = ie ? 0x80 : 0x00;
2578   bb |= Ds << 2;
2579   bb |= Dp;
2580 
2581   char *f = s12z_new_insn (3);
2582   number_to_chars_bigendian (f++, PAGE2_PREBYTE, 1);
2583   number_to_chars_bigendian (f++, 0x08 | Dd, 1);
2584   number_to_chars_bigendian (f++, bb , 1);
2585 
2586   return true;
2587 
2588  fail:
2589   fail_line_pointer = input_line_pointer;
2590   input_line_pointer = ilp;
2591   return false;
2592 }
2593 
2594 static bool
bf_opr_reg_reg(const struct instruction * insn,short ie)2595 bf_opr_reg_reg  (const struct instruction *insn, short ie)
2596 {
2597   char *ilp = input_line_pointer;
2598 
2599   uint8_t buffer[4];
2600   int n_bytes;
2601   expressionS exp;
2602   if (!lex_opr (buffer, &n_bytes, &exp, false))
2603     goto fail;
2604 
2605   if (!lex_match (','))
2606     goto fail;
2607 
2608 
2609   int Ds = 0;
2610   if (!lex_reg_name (REG_BIT_Dn, &Ds))
2611     goto fail;
2612 
2613   if (!lex_match (','))
2614     goto fail;
2615 
2616 
2617   int Dp = 0;
2618   if (!lex_reg_name  ((0x01u << REG_D2) |
2619 		      (0x01u << REG_D3) |
2620 		      (0x01u << REG_D4) |
2621 		      (0x01u << REG_D5),
2622 		      &Dp))
2623     goto fail;
2624 
2625   int size = size_from_suffix (insn, 0);
2626   uint8_t bb = ie ? 0x80 : 0x00;
2627   bb |= 0x50;
2628   bb |= Dp;
2629   bb |= (size - 1) << 2;
2630 
2631   char *f = s12z_new_insn (3 + n_bytes);
2632   number_to_chars_bigendian (f++, PAGE2_PREBYTE, 1);
2633   number_to_chars_bigendian (f++, 0x08 | Ds, 1);
2634   number_to_chars_bigendian (f++, bb , 1);
2635 
2636   emit_opr (f, buffer, n_bytes, &exp);
2637 
2638   return true;
2639 
2640  fail:
2641   fail_line_pointer = input_line_pointer;
2642   input_line_pointer = ilp;
2643   return false;
2644 }
2645 
2646 
2647 static bool
bf_reg_opr_reg(const struct instruction * insn,short ie)2648 bf_reg_opr_reg  (const struct instruction *insn, short ie)
2649 {
2650   char *ilp = input_line_pointer;
2651   int Dd = 0;
2652   if (!lex_reg_name (REG_BIT_Dn, &Dd))
2653     goto fail;
2654 
2655   if (!lex_match (','))
2656     goto fail;
2657 
2658 
2659   uint8_t buffer[4];
2660   int n_bytes;
2661   expressionS exp;
2662   if (!lex_opr (buffer, &n_bytes, &exp, false))
2663     goto fail;
2664 
2665   if (!lex_match (','))
2666     goto fail;
2667 
2668   int Dp = 0;
2669   if (!lex_reg_name  ((0x01u << REG_D2) |
2670 		      (0x01u << REG_D3) |
2671 		      (0x01u << REG_D4) |
2672 		      (0x01u << REG_D5),
2673 		      &Dp))
2674     goto fail;
2675 
2676   int size = size_from_suffix (insn, 0);
2677   uint8_t bb = ie ? 0x80 : 0x00;
2678   bb |= 0x40;
2679   bb |= Dp;
2680   bb |= (size - 1) << 2;
2681 
2682   char *f = s12z_new_insn (3 + n_bytes);
2683   number_to_chars_bigendian (f++, PAGE2_PREBYTE, 1);
2684   number_to_chars_bigendian (f++, 0x08 | Dd, 1);
2685   number_to_chars_bigendian (f++, bb , 1);
2686 
2687   emit_opr (f, buffer, n_bytes, &exp);
2688 
2689   return true;
2690 
2691  fail:
2692   fail_line_pointer = input_line_pointer;
2693   input_line_pointer = ilp;
2694   return false;
2695 }
2696 
2697 
2698 
2699 static bool
bfe_reg_reg_reg(const struct instruction * insn)2700 bfe_reg_reg_reg  (const struct instruction *insn)
2701 {
2702   return bf_reg_reg_reg (insn, 0);
2703 }
2704 
2705 static bool
bfi_reg_reg_reg(const struct instruction * insn)2706 bfi_reg_reg_reg  (const struct instruction *insn)
2707 {
2708   return bf_reg_reg_reg (insn, 1);
2709 }
2710 
2711 static bool
bfe_reg_reg_imm(const struct instruction * insn)2712 bfe_reg_reg_imm  (const struct instruction *insn)
2713 {
2714   return bf_reg_reg_imm (insn, 0);
2715 }
2716 
2717 static bool
bfi_reg_reg_imm(const struct instruction * insn)2718 bfi_reg_reg_imm  (const struct instruction *insn)
2719 {
2720   return bf_reg_reg_imm (insn, 1);
2721 }
2722 
2723 
2724 static bool
bfe_reg_opr_reg(const struct instruction * insn)2725 bfe_reg_opr_reg  (const struct instruction *insn)
2726 {
2727   return bf_reg_opr_reg (insn, 0);
2728 }
2729 
2730 static bool
bfi_reg_opr_reg(const struct instruction * insn)2731 bfi_reg_opr_reg  (const struct instruction *insn)
2732 {
2733   return bf_reg_opr_reg (insn, 1);
2734 }
2735 
2736 
2737 static bool
bfe_opr_reg_reg(const struct instruction * insn)2738 bfe_opr_reg_reg  (const struct instruction *insn)
2739 {
2740   return bf_opr_reg_reg (insn, 0);
2741 }
2742 
2743 static bool
bfi_opr_reg_reg(const struct instruction * insn)2744 bfi_opr_reg_reg  (const struct instruction *insn)
2745 {
2746   return bf_opr_reg_reg (insn, 1);
2747 }
2748 
2749 static bool
bfe_reg_opr_imm(const struct instruction * insn)2750 bfe_reg_opr_imm  (const struct instruction *insn)
2751 {
2752   return bf_reg_opr_imm (insn, 0);
2753 }
2754 
2755 static bool
bfi_reg_opr_imm(const struct instruction * insn)2756 bfi_reg_opr_imm  (const struct instruction *insn)
2757 {
2758   return bf_reg_opr_imm (insn, 1);
2759 }
2760 
2761 static bool
bfe_opr_reg_imm(const struct instruction * insn)2762 bfe_opr_reg_imm  (const struct instruction *insn)
2763 {
2764   return bf_opr_reg_imm (insn, 0);
2765 }
2766 
2767 static bool
bfi_opr_reg_imm(const struct instruction * insn)2768 bfi_opr_reg_imm  (const struct instruction *insn)
2769 {
2770   return bf_opr_reg_imm (insn, 1);
2771 }
2772 
2773 
2774 
2775 
2776 static bool
tb_reg_rel(const struct instruction * insn)2777 tb_reg_rel  (const struct instruction *insn)
2778 {
2779   char *ilp = input_line_pointer;
2780 
2781   int reg;
2782   if (!lex_reg_name (REG_BIT_Dn | REG_BIT_XY, &reg))
2783     goto fail;
2784 
2785   if (!lex_match (','))
2786     goto fail;
2787 
2788   bool long_displacement;
2789   expressionS exp;
2790   if (! lex_15_bit_offset (&long_displacement, &exp))
2791     goto fail;
2792 
2793   uint8_t lb = 0x00;
2794   if (reg == REG_X || reg == REG_Y)
2795     {
2796       lb |= 0x08;
2797     }
2798   else
2799     {
2800       lb |= reg;
2801     }
2802   if (reg == REG_Y)
2803     lb |= 0x01;
2804 
2805   if (startswith (insn->name + 2, "ne"))
2806     lb |= 0x00 << 4;
2807   else if (startswith (insn->name + 2, "eq"))
2808     lb |= 0x01 << 4;
2809   else if (startswith (insn->name + 2, "pl"))
2810     lb |= 0x02 << 4;
2811   else if (startswith (insn->name + 2, "mi"))
2812     lb |= 0x03 << 4;
2813   else if (startswith (insn->name + 2, "gt"))
2814     lb |= 0x04 << 4;
2815   else if (startswith (insn->name + 2, "le"))
2816     lb |= 0x05 << 4;
2817 
2818   switch (insn->name[0])
2819     {
2820     case 'd':
2821       lb |= 0x80;
2822       break;
2823     case 't':
2824       break;
2825     default:
2826       gas_assert (0);
2827       break;
2828     };
2829 
2830   char *f = s12z_new_insn (long_displacement ? 4 : 3);
2831   number_to_chars_bigendian (f++, insn->opc, 1);
2832   number_to_chars_bigendian (f++, lb, 1);
2833 
2834   emit_15_bit_offset (f, 4, &exp);
2835 
2836   return true;
2837 
2838  fail:
2839   fail_line_pointer = input_line_pointer;
2840   input_line_pointer = ilp;
2841   return false;
2842 }
2843 
2844 
2845 static bool
tb_opr_rel(const struct instruction * insn)2846 tb_opr_rel  (const struct instruction *insn)
2847 {
2848   char *ilp = input_line_pointer;
2849 
2850   uint8_t buffer[4];
2851   int n_bytes;
2852   expressionS exp;
2853   if (!lex_opr (buffer, &n_bytes, &exp, false))
2854     goto fail;
2855 
2856   if (!lex_match (','))
2857     goto fail;
2858 
2859   bool long_displacement;
2860   expressionS exp2;
2861   if (! lex_15_bit_offset (&long_displacement, &exp2))
2862     goto fail;
2863 
2864   uint8_t lb = 0x0C;
2865 
2866   if (startswith (insn->name + 2, "ne"))
2867     lb |= 0x00 << 4;
2868   else if (startswith (insn->name + 2, "eq"))
2869     lb |= 0x01 << 4;
2870   else if (startswith (insn->name + 2, "pl"))
2871     lb |= 0x02 << 4;
2872   else if (startswith (insn->name + 2, "mi"))
2873     lb |= 0x03 << 4;
2874   else if (startswith (insn->name + 2, "gt"))
2875     lb |= 0x04 << 4;
2876   else if (startswith (insn->name + 2, "le"))
2877     lb |= 0x05 << 4;
2878 
2879   switch (insn->name[0])
2880     {
2881     case 'd':
2882       lb |= 0x80;
2883       break;
2884     case 't':
2885       break;
2886     default:
2887       gas_assert (0);
2888       break;
2889     };
2890 
2891   int size = size_from_suffix (insn, 0);
2892 
2893   lb |= size -1;
2894 
2895   char *f = s12z_new_insn (n_bytes + (long_displacement ? 4 : 3));
2896   number_to_chars_bigendian (f++, insn->opc, 1);
2897   number_to_chars_bigendian (f++, lb, 1);
2898   f = emit_opr (f, buffer, n_bytes, &exp);
2899 
2900   emit_15_bit_offset (f, n_bytes + 4, &exp2);
2901 
2902   return true;
2903 
2904  fail:
2905   fail_line_pointer = input_line_pointer;
2906   input_line_pointer = ilp;
2907   return false;
2908 }
2909 
2910 
2911 
2912 
2913 static bool
test_br_reg_reg_rel(const struct instruction * insn)2914 test_br_reg_reg_rel  (const struct instruction *insn)
2915 {
2916   char *ilp = input_line_pointer;
2917 
2918   int Di = 0;
2919   if (!lex_reg_name (REG_BIT_Dn, &Di))
2920     goto fail;
2921 
2922   if (!lex_match (','))
2923     goto fail;
2924 
2925 
2926   int Dn = 0;
2927   if (!lex_reg_name (REG_BIT_Dn, &Dn))
2928     goto fail;
2929 
2930   if (!lex_match (','))
2931     goto fail;
2932 
2933 
2934   bool long_displacement;
2935   expressionS exp;
2936   if (! lex_15_bit_offset (&long_displacement, &exp))
2937     goto fail;
2938 
2939   uint8_t bm = 0x81;
2940   uint8_t xb = 0xb8;
2941 
2942   bm |= Dn << 4;
2943   xb |= Di;
2944 
2945   char *f = s12z_new_insn (long_displacement ? 5 : 4);
2946   number_to_chars_bigendian (f++, insn->opc, 1);
2947   number_to_chars_bigendian (f++, bm, 1);
2948   number_to_chars_bigendian (f++, xb, 1);
2949 
2950   emit_15_bit_offset (f, 5, &exp);
2951 
2952   return true;
2953 
2954  fail:
2955   fail_line_pointer = input_line_pointer;
2956   input_line_pointer = ilp;
2957   return false;
2958 }
2959 
2960 static bool
test_br_opr_reg_rel(const struct instruction * insn)2961 test_br_opr_reg_rel  (const struct instruction *insn)
2962 {
2963   char *ilp = input_line_pointer;
2964 
2965   uint8_t buffer[4];
2966   int n_bytes;
2967   expressionS exp;
2968   if (!lex_opr (buffer, &n_bytes,  &exp, false))
2969     goto fail;
2970 
2971   if (!lex_match (','))
2972     goto fail;
2973 
2974   int Dn = 0;
2975   if (!lex_reg_name (REG_BIT_Dn, &Dn))
2976     goto fail;
2977 
2978   if (!lex_match (','))
2979     goto fail;
2980 
2981   uint8_t bm = 0x81;
2982   bm |= Dn << 4;
2983   int size = size_from_suffix (insn, 0);
2984   bm |= (size -1) << 2;
2985 
2986   bool long_displacement;
2987 
2988   expressionS exp2;
2989   if (! lex_15_bit_offset (&long_displacement, &exp2))
2990     goto fail;
2991 
2992   int n = n_bytes + (long_displacement ? 4 : 3);
2993   char *f = s12z_new_insn (n);
2994   number_to_chars_bigendian (f++, insn->opc, 1);
2995   number_to_chars_bigendian (f++, bm, 1);
2996   f = emit_opr (f, buffer, n_bytes, &exp);
2997 
2998   emit_15_bit_offset (f, n, &exp2);
2999 
3000   return true;
3001 
3002  fail:
3003   fail_line_pointer = input_line_pointer;
3004   input_line_pointer = ilp;
3005   return false;
3006 }
3007 
3008 
3009 static bool
test_br_opr_imm_rel(const struct instruction * insn)3010 test_br_opr_imm_rel  (const struct instruction *insn)
3011 {
3012   char *ilp = input_line_pointer;
3013 
3014   uint8_t buffer[4];
3015   int n_bytes;
3016   expressionS exp;
3017   if (!lex_opr (buffer, &n_bytes, &exp, false))
3018     goto fail;
3019 
3020   if (!lex_match (','))
3021     goto fail;
3022 
3023   long imm;
3024   if (!lex_imm (&imm, NULL))
3025     goto fail;
3026 
3027   if (imm < 0 || imm > 31)
3028     goto fail;
3029 
3030   if (!lex_match (','))
3031     goto fail;
3032 
3033   bool long_displacement;
3034   expressionS exp2;
3035   if (! lex_15_bit_offset (&long_displacement, &exp2))
3036     goto fail;
3037 
3038   int size = size_from_suffix (insn, 0);
3039 
3040   uint8_t bm = 0x80;
3041   bm |= (imm & 0x07) << 4;
3042   bm |= (imm >> 3) & 0x03;
3043   if (size == 4)
3044     bm |=  0x08;
3045   else if  (size == 2)
3046     bm |= 0x02;
3047 
3048   char *f = s12z_new_insn (n_bytes + (long_displacement ? 4 : 3));
3049   number_to_chars_bigendian (f++, insn->opc, 1);
3050   number_to_chars_bigendian (f++, bm, 1);
3051   f = emit_opr (f, buffer, n_bytes, &exp);
3052 
3053   emit_15_bit_offset (f, n_bytes + 4,  &exp2);
3054 
3055   return true;
3056 
3057  fail:
3058   fail_line_pointer = input_line_pointer;
3059   input_line_pointer = ilp;
3060   return false;
3061 }
3062 
3063 
3064 static bool
test_br_reg_imm_rel(const struct instruction * insn)3065 test_br_reg_imm_rel  (const struct instruction *insn)
3066 {
3067   char *ilp = input_line_pointer;
3068 
3069   int Di = 0;
3070   if (!lex_reg_name (REG_BIT_Dn, &Di))
3071     goto fail;
3072 
3073   if (!lex_match (','))
3074     goto fail;
3075 
3076   long imm;
3077   if (!lex_imm (&imm, NULL))
3078     goto fail;
3079 
3080   if (imm < 0 || imm > 31)
3081     goto fail;
3082 
3083 
3084   if (!lex_match (','))
3085     goto fail;
3086 
3087   bool long_displacement;
3088   expressionS exp;
3089   if (! lex_15_bit_offset (&long_displacement, &exp))
3090     goto fail;
3091 
3092   uint8_t bm = Di;
3093   bm |= imm << 3;
3094 
3095   char *f = s12z_new_insn (long_displacement ? 4 : 3);
3096   number_to_chars_bigendian (f++, insn->opc, 1);
3097   number_to_chars_bigendian (f++, bm, 1);
3098 
3099   emit_15_bit_offset (f, 4, &exp);
3100 
3101   return true;
3102 
3103  fail:
3104   fail_line_pointer = input_line_pointer;
3105   input_line_pointer = ilp;
3106   return false;
3107 }
3108 
3109 
3110 
3111 
3112 static const struct instruction opcodes[] = {
3113   {"bgnd", 1,  0x00,  no_operands, 0},
3114   {"nop", 1,   0x01,  no_operands, 0},
3115 
3116   {"brclr", 1, 0x02,  test_br_reg_reg_rel, 0},
3117   {"brset", 1, 0x03,  test_br_reg_reg_rel, 0},
3118 
3119   {"brclr", 1, 0x02,  test_br_reg_imm_rel, 0},
3120   {"brset", 1, 0x03,  test_br_reg_imm_rel, 0},
3121 
3122   {"brclr.b", 1, 0x02, test_br_opr_reg_rel, 0},
3123   {"brclr.w", 1, 0x02, test_br_opr_reg_rel, 0},
3124   {"brclr.l", 1, 0x02, test_br_opr_reg_rel, 0},
3125 
3126   {"brset.b", 1, 0x03, test_br_opr_reg_rel, 0},
3127   {"brset.w", 1, 0x03, test_br_opr_reg_rel, 0},
3128   {"brset.l", 1, 0x03, test_br_opr_reg_rel, 0},
3129 
3130   {"brclr.b", 1, 0x02, test_br_opr_imm_rel, 0},
3131   {"brclr.w", 1, 0x02, test_br_opr_imm_rel, 0},
3132   {"brclr.l", 1, 0x02, test_br_opr_imm_rel, 0},
3133 
3134   {"brset.b", 1, 0x03, test_br_opr_imm_rel, 0},
3135   {"brset.w", 1, 0x03, test_br_opr_imm_rel, 0},
3136   {"brset.l", 1, 0x03, test_br_opr_imm_rel, 0},
3137 
3138   {"psh", 1,   0x04,  psh_pull, 0},
3139   {"pul", 1,   0x04,  psh_pull, 0},
3140 
3141   {"rts", 1,   0x05,  no_operands, 0},
3142   {"lea", 1,   0x06,  reg67sxy_opr, 0},
3143 
3144   {"dbne", 1,  0x0b,  tb_reg_rel, 0},
3145   {"dbeq", 1,  0x0b,  tb_reg_rel, 0},
3146   {"dbpl", 1,  0x0b,  tb_reg_rel, 0},
3147   {"dbmi", 1,  0x0b,  tb_reg_rel, 0},
3148   {"dbgt", 1,  0x0b,  tb_reg_rel, 0},
3149   {"dble", 1,  0x0b,  tb_reg_rel, 0},
3150 
3151   {"dbne.b", 1,  0x0b,  tb_opr_rel, 0},
3152   {"dbeq.b", 1,  0x0b,  tb_opr_rel, 0},
3153   {"dbpl.b", 1,  0x0b,  tb_opr_rel, 0},
3154   {"dbmi.b", 1,  0x0b,  tb_opr_rel, 0},
3155   {"dbgt.b", 1,  0x0b,  tb_opr_rel, 0},
3156   {"dble.b", 1,  0x0b,  tb_opr_rel, 0},
3157 
3158   {"dbne.w", 1,  0x0b,  tb_opr_rel, 0},
3159   {"dbeq.w", 1,  0x0b,  tb_opr_rel, 0},
3160   {"dbpl.w", 1,  0x0b,  tb_opr_rel, 0},
3161   {"dbmi.w", 1,  0x0b,  tb_opr_rel, 0},
3162   {"dbgt.w", 1,  0x0b,  tb_opr_rel, 0},
3163   {"dble.w", 1,  0x0b,  tb_opr_rel, 0},
3164 
3165   {"dbne.p", 1,  0x0b,  tb_opr_rel, 0},
3166   {"dbeq.p", 1,  0x0b,  tb_opr_rel, 0},
3167   {"dbpl.p", 1,  0x0b,  tb_opr_rel, 0},
3168   {"dbmi.p", 1,  0x0b,  tb_opr_rel, 0},
3169   {"dbgt.p", 1,  0x0b,  tb_opr_rel, 0},
3170   {"dble.p", 1,  0x0b,  tb_opr_rel, 0},
3171 
3172   {"dbne.l", 1,  0x0b,  tb_opr_rel, 0},
3173   {"dbeq.l", 1,  0x0b,  tb_opr_rel, 0},
3174   {"dbpl.l", 1,  0x0b,  tb_opr_rel, 0},
3175   {"dbmi.l", 1,  0x0b,  tb_opr_rel, 0},
3176   {"dbgt.l", 1,  0x0b,  tb_opr_rel, 0},
3177   {"dble.l", 1,  0x0b,  tb_opr_rel, 0},
3178 
3179   {"tbne", 1,  0x0b,  tb_reg_rel, 0},
3180   {"tbeq", 1,  0x0b,  tb_reg_rel, 0},
3181   {"tbpl", 1,  0x0b,  tb_reg_rel, 0},
3182   {"tbmi", 1,  0x0b,  tb_reg_rel, 0},
3183   {"tbgt", 1,  0x0b,  tb_reg_rel, 0},
3184   {"tble", 1,  0x0b,  tb_reg_rel, 0},
3185 
3186   {"tbne.b", 1,  0x0b,  tb_opr_rel, 0},
3187   {"tbeq.b", 1,  0x0b,  tb_opr_rel, 0},
3188   {"tbpl.b", 1,  0x0b,  tb_opr_rel, 0},
3189   {"tbmi.b", 1,  0x0b,  tb_opr_rel, 0},
3190   {"tbgt.b", 1,  0x0b,  tb_opr_rel, 0},
3191   {"tble.b", 1,  0x0b,  tb_opr_rel, 0},
3192 
3193   {"tbne.w", 1,  0x0b,  tb_opr_rel, 0},
3194   {"tbeq.w", 1,  0x0b,  tb_opr_rel, 0},
3195   {"tbpl.w", 1,  0x0b,  tb_opr_rel, 0},
3196   {"tbmi.w", 1,  0x0b,  tb_opr_rel, 0},
3197   {"tbgt.w", 1,  0x0b,  tb_opr_rel, 0},
3198   {"tble.w", 1,  0x0b,  tb_opr_rel, 0},
3199 
3200   {"tbne.p", 1,  0x0b,  tb_opr_rel, 0},
3201   {"tbeq.p", 1,  0x0b,  tb_opr_rel, 0},
3202   {"tbpl.p", 1,  0x0b,  tb_opr_rel, 0},
3203   {"tbmi.p", 1,  0x0b,  tb_opr_rel, 0},
3204   {"tbgt.p", 1,  0x0b,  tb_opr_rel, 0},
3205   {"tble.p", 1,  0x0b,  tb_opr_rel, 0},
3206 
3207   {"tbne.l", 1,  0x0b,  tb_opr_rel, 0},
3208   {"tbeq.l", 1,  0x0b,  tb_opr_rel, 0},
3209   {"tbpl.l", 1,  0x0b,  tb_opr_rel, 0},
3210   {"tbmi.l", 1,  0x0b,  tb_opr_rel, 0},
3211   {"tbgt.l", 1,  0x0b,  tb_opr_rel, 0},
3212   {"tble.l", 1,  0x0b,  tb_opr_rel, 0},
3213 
3214   {"mov.b", 1, 0x0c,  imm_opr, 0},
3215   {"mov.w", 1, 0x0d,  imm_opr, 0},
3216   {"mov.p", 1, 0x0e,  imm_opr, 0},
3217   {"mov.l", 1, 0x0f,  imm_opr, 0},
3218 
3219   {"rol",   1, 0x10,  rol, 0},
3220   {"rol.b", 1, 0x10,  rol, 0},
3221   {"rol.w", 1, 0x10,  rol, 0},
3222   {"rol.p", 1, 0x10,  rol, 0},
3223   {"rol.l", 1, 0x10,  rol, 0},
3224 
3225   {"ror",   1, 0x10,  ror, 0},
3226   {"ror.b", 1, 0x10,  ror, 0},
3227   {"ror.w", 1, 0x10,  ror, 0},
3228   {"ror.p", 1, 0x10,  ror, 0},
3229   {"ror.l", 1, 0x10,  ror, 0},
3230 
3231   {"lsl", 1,   0x10,  shift_reg, 0},
3232   {"lsr", 1,   0x10,  shift_reg, 0},
3233   {"asl", 1,   0x10,  shift_reg, 0},
3234   {"asr", 1,   0x10,  shift_reg, 0},
3235 
3236   {"lsl.b", 1, 0x10,  shift_two_operand, 0},
3237   {"lsl.w", 1, 0x10,  shift_two_operand, 0},
3238   {"lsl.p", 1, 0x10,  shift_two_operand, 0},
3239   {"lsl.l", 1, 0x10,  shift_two_operand, 0},
3240   {"asl.b", 1, 0x10,  shift_two_operand, 0},
3241   {"asl.w", 1, 0x10,  shift_two_operand, 0},
3242   {"asl.p", 1, 0x10,  shift_two_operand, 0},
3243   {"asl.l", 1, 0x10,  shift_two_operand, 0},
3244 
3245   {"lsr.b", 1, 0x10,  shift_two_operand, 0},
3246   {"lsr.w", 1, 0x10,  shift_two_operand, 0},
3247   {"lsr.p", 1, 0x10,  shift_two_operand, 0},
3248   {"lsr.l", 1, 0x10,  shift_two_operand, 0},
3249   {"asr.b", 1, 0x10,  shift_two_operand, 0},
3250   {"asr.w", 1, 0x10,  shift_two_operand, 0},
3251   {"asr.p", 1, 0x10,  shift_two_operand, 0},
3252   {"asr.l", 1, 0x10,  shift_two_operand, 0},
3253 
3254   {"lsl.b", 1, 0x10,  shift_opr_imm, 0},
3255   {"lsl.w", 1, 0x10,  shift_opr_imm, 0},
3256   {"lsl.p", 1, 0x10,  shift_opr_imm, 0},
3257   {"lsl.l", 1, 0x10,  shift_opr_imm, 0},
3258   {"asl.b", 1, 0x10,  shift_opr_imm, 0},
3259   {"asl.w", 1, 0x10,  shift_opr_imm, 0},
3260   {"asl.p", 1, 0x10,  shift_opr_imm, 0},
3261   {"asl.l", 1, 0x10,  shift_opr_imm, 0},
3262 
3263   {"lsr.b", 1, 0x10,  shift_opr_imm, 0},
3264   {"lsr.w", 1, 0x10,  shift_opr_imm, 0},
3265   {"lsr.p", 1, 0x10,  shift_opr_imm, 0},
3266   {"lsr.l", 1, 0x10,  shift_opr_imm, 0},
3267   {"asr.b", 1, 0x10,  shift_opr_imm, 0},
3268   {"asr.w", 1, 0x10,  shift_opr_imm, 0},
3269   {"asr.p", 1, 0x10,  shift_opr_imm, 0},
3270   {"asr.l", 1, 0x10,  shift_opr_imm, 0},
3271 
3272   {"mov.b", 1, 0x1c,  opr_opr, 0},
3273   {"mov.w", 1, 0x1d,  opr_opr, 0},
3274   {"mov.p", 1, 0x1e,  opr_opr, 0},
3275   {"mov.l", 1, 0x1f,  opr_opr, 0},
3276 
3277   {"bra", 1,   0x20,  rel, 0},
3278   {"bsr", 1,   0x21,  rel, 0},
3279   {"bhi", 1,   0x22,  rel, 0},
3280   {"bls", 1,   0x23,  rel, 0},
3281   {"bcc", 1,   0x24,  rel, 0},
3282   {"bhs", 1,   0x24,  rel, 0}, /* Alias for bcc */
3283   {"bcs", 1,   0x25,  rel, 0},
3284   {"blo", 1,   0x25,  rel, 0}, /* Alias for bcs */
3285   {"bne", 1,   0x26,  rel, 0},
3286   {"beq", 1,   0x27,  rel, 0},
3287   {"bvc", 1,   0x28,  rel, 0},
3288   {"bvs", 1,   0x29,  rel, 0},
3289   {"bpl", 1,   0x2a,  rel, 0},
3290   {"bmi", 1,   0x2b,  rel, 0},
3291   {"bge", 1,   0x2c,  rel, 0},
3292   {"blt", 1,   0x2d,  rel, 0},
3293   {"bgt", 1,   0x2e,  rel, 0},
3294   {"ble", 1,   0x2f,  rel, 0},
3295 
3296   {"inc", 1,   0x30,  reg_inh, 0},
3297   {"clr", 1,   0x38,  reg_inh, 0},
3298   {"dec", 1,   0x40,  reg_inh, 0},
3299 
3300   {"muls", 1,  0x48,  mul_reg_reg_reg, 0},
3301   {"mulu", 1,  0x48,  mul_reg_reg_reg, 0},
3302 
3303   {"muls.b", 1,  0x48,  mul_reg_reg_opr, 0},
3304   {"muls.w", 1,  0x48,  mul_reg_reg_opr, 0},
3305   {"muls.l", 1,  0x48,  mul_reg_reg_opr, 0},
3306 
3307   {"mulu.b", 1,  0x48,  mul_reg_reg_opr, 0},
3308   {"mulu.w", 1,  0x48,  mul_reg_reg_opr, 0},
3309   {"mulu.l", 1,  0x48,  mul_reg_reg_opr, 0},
3310 
3311   {"muls.b", 1,  0x48,  mul_reg_reg_imm, 0},
3312   {"muls.w", 1,  0x48,  mul_reg_reg_imm, 0},
3313   {"muls.l", 1,  0x48,  mul_reg_reg_imm, 0},
3314 
3315   {"mulu.b", 1,  0x48,  mul_reg_reg_imm, 0},
3316   {"mulu.w", 1,  0x48,  mul_reg_reg_imm, 0},
3317   {"mulu.l", 1,  0x48,  mul_reg_reg_imm, 0},
3318 
3319   {"muls.bb", 1,  0x48,  mul_reg_opr_opr, 0},
3320   {"muls.bw", 1,  0x48,  mul_reg_opr_opr, 0},
3321   {"muls.bp", 1,  0x48,  mul_reg_opr_opr, 0},
3322   {"muls.bl", 1,  0x48,  mul_reg_opr_opr, 0},
3323 
3324   {"muls.wb", 1,  0x48,  mul_reg_opr_opr, 0},
3325   {"muls.ww", 1,  0x48,  mul_reg_opr_opr, 0},
3326   {"muls.wp", 1,  0x48,  mul_reg_opr_opr, 0},
3327   {"muls.wl", 1,  0x48,  mul_reg_opr_opr, 0},
3328 
3329   {"muls.pb", 1,  0x48,  mul_reg_opr_opr, 0},
3330   {"muls.pw", 1,  0x48,  mul_reg_opr_opr, 0},
3331   {"muls.pp", 1,  0x48,  mul_reg_opr_opr, 0},
3332   {"muls.pl", 1,  0x48,  mul_reg_opr_opr, 0},
3333 
3334   {"muls.lb", 1,  0x48,  mul_reg_opr_opr, 0},
3335   {"muls.lw", 1,  0x48,  mul_reg_opr_opr, 0},
3336   {"muls.lp", 1,  0x48,  mul_reg_opr_opr, 0},
3337   {"muls.ll", 1,  0x48,  mul_reg_opr_opr, 0},
3338 
3339   {"mulu.bb", 1,  0x48,  mul_reg_opr_opr, 0},
3340   {"mulu.bw", 1,  0x48,  mul_reg_opr_opr, 0},
3341   {"mulu.bp", 1,  0x48,  mul_reg_opr_opr, 0},
3342   {"mulu.bl", 1,  0x48,  mul_reg_opr_opr, 0},
3343 
3344   {"mulu.wb", 1,  0x48,  mul_reg_opr_opr, 0},
3345   {"mulu.ww", 1,  0x48,  mul_reg_opr_opr, 0},
3346   {"mulu.wp", 1,  0x48,  mul_reg_opr_opr, 0},
3347   {"mulu.wl", 1,  0x48,  mul_reg_opr_opr, 0},
3348 
3349   {"mulu.pb", 1,  0x48,  mul_reg_opr_opr, 0},
3350   {"mulu.pw", 1,  0x48,  mul_reg_opr_opr, 0},
3351   {"mulu.pp", 1,  0x48,  mul_reg_opr_opr, 0},
3352   {"mulu.pl", 1,  0x48,  mul_reg_opr_opr, 0},
3353 
3354   {"mulu.lb", 1,  0x48,  mul_reg_opr_opr, 0},
3355   {"mulu.lw", 1,  0x48,  mul_reg_opr_opr, 0},
3356   {"mulu.lp", 1,  0x48,  mul_reg_opr_opr, 0},
3357   {"mulu.ll", 1,  0x48,  mul_reg_opr_opr, 0},
3358 
3359   {"add", 1,   0x50,  regd_imm, 0},
3360   {"and", 1,   0x58,  regd_imm, 0},
3361 
3362   {"add", 1,   0x60,  regd_opr, 0},
3363   {"and", 1,   0x68,  regd_opr, 0},
3364 
3365   {"sub", 1,   0x70,  regd_imm, 0},
3366   {"or", 1,    0x78,  regd_imm, 0},
3367 
3368   {"sub", 1,   0x80,  regd_opr, 0},
3369   {"or",  1,    0x88,  regd_opr, 0},
3370 
3371   {"ld",  1,    0x90,  regdxy_imm, 0},
3372 
3373   {"clr", 1,   0x9a,  clr_xy, 0},
3374   {"tfr", 1,   0x9e,  tfr, 0},
3375   {"zex", 1,   0x9e,  tfr, 0},
3376 
3377   {"ld",  1,   0xa0,  regdxy_opr_src, 0xb0},
3378 
3379   {"jmp", 1,   0xaa,  opr, 0xba},
3380   {"jsr", 1,   0xab,  opr, 0xbb},
3381 
3382   {"exg", 1,   0xae,  tfr, 0},
3383   {"sex", 1,   0xae,  tfr, 0},
3384 
3385   {"st", 1,    0xc0,  regdxy_opr_dest, 0xd0},
3386 
3387   {"andcc", 1, 0xce,  imm8, 0},
3388   {"orcc", 1,  0xde,  imm8, 0},
3389 
3390   {"inc.b", 1, 0x9c,  opr, 0},
3391   {"inc.w", 1, 0x9d,  opr, 0},
3392   {"inc.l", 1, 0x9f,  opr, 0},
3393 
3394   {"dec.b", 1, 0xac,  opr, 0},
3395   {"dec.w", 1, 0xad,  opr, 0},
3396   {"dec.l", 1, 0xaf,  opr, 0},
3397 
3398   {"clr.b", 1, 0xbc,  opr, 0},
3399   {"clr.w", 1, 0xbd,  opr, 0},
3400   {"clr.p", 1, 0xbe,  opr, 0},
3401   {"clr.l", 1, 0xbf,  opr, 0},
3402 
3403   {"com.b", 1, 0xcc,  opr, 0},
3404   {"com.w", 1, 0xcd,  opr, 0},
3405   {"com.l", 1, 0xcf,  opr, 0},
3406 
3407   {"neg.b", 1, 0xdc,  opr, 0},
3408   {"neg.w", 1, 0xdd,  opr, 0},
3409   {"neg.l", 1, 0xdf,  opr, 0},
3410 
3411   {"bclr",  1, 0xec, bm_regd_imm, 0},
3412   {"bset",  1, 0xed, bm_regd_imm, 0},
3413   {"btgl",  1, 0xee, bm_regd_imm, 0},
3414 
3415   {"bclr",  1, 0xec, bm_regd_reg, 0},
3416   {"bset",  1, 0xed, bm_regd_reg, 0},
3417   {"btgl",  1, 0xee, bm_regd_reg, 0},
3418 
3419   {"bclr.b",  1, 0xec, bm_opr_imm, 0},
3420   {"bclr.w",  1, 0xec, bm_opr_imm, 0},
3421   {"bclr.l",  1, 0xec, bm_opr_imm, 0},
3422 
3423   {"bset.b",  1, 0xed, bm_opr_imm, 0},
3424   {"bset.w",  1, 0xed, bm_opr_imm, 0},
3425   {"bset.l",  1, 0xed, bm_opr_imm, 0},
3426 
3427   {"btgl.b",  1, 0xee, bm_opr_imm, 0},
3428   {"btgl.w",  1, 0xee, bm_opr_imm, 0},
3429   {"btgl.l",  1, 0xee, bm_opr_imm, 0},
3430 
3431   {"bclr.b",  1, 0xec, bm_opr_reg, 0},
3432   {"bclr.w",  1, 0xec, bm_opr_reg, 0},
3433   {"bclr.l",  1, 0xec, bm_opr_reg, 0},
3434 
3435   {"bset.b",  1, 0xed, bm_opr_reg, 0},
3436   {"bset.w",  1, 0xed, bm_opr_reg, 0},
3437   {"bset.l",  1, 0xed, bm_opr_reg, 0},
3438 
3439   {"btgl.b",  1, 0xee, bm_opr_reg, 0},
3440   {"btgl.w",  1, 0xee, bm_opr_reg, 0},
3441   {"btgl.l",  1, 0xee, bm_opr_reg, 0},
3442 
3443   {"cmp", 1,   0xe0,  regdxy_imm, 0},
3444   {"cmp", 1,   0xf0,  regdxy_opr_src, 0},
3445 
3446   {"cmp", 1,   0xfc,  regx_regy, 0},
3447   {"sub", 1,   0xfd,  regd6_regx_regy, 0},
3448   {"sub", 1,   0xfe,  regd6_regy_regx, 0},
3449 
3450   {"swi", 1,   0xff,  no_operands, 0},
3451 
3452   /* Page 2 */
3453 
3454   /* The -10 below is a kludge.  The opcode is in fact 0x00 */
3455   {"ld",    2,  -10,  regs_opr_src, 0},
3456 
3457   /* The -9 below is a kludge.  The opcode is in fact 0x01 */
3458   {"st",    2,  -9,  regs_opr_dest, 0},
3459 
3460   /* The -8 below is a kludge.  The opcode is in fact 0x02 */
3461   {"cmp",    2,  -8,  regs_opr_src, 0},
3462 
3463   /* The -7 below is a kludge.  The opcode is in fact 0x03 */
3464   {"ld",    2,  -7,  regs_imm, 0},
3465 
3466   /* The -6 below is a kludge.  The opcode is in fact 0x04 */
3467   {"cmp",    2,  -6,  regs_imm, 0},
3468 
3469   {"bfext",   2,  0x08,  bfe_reg_reg_reg, 0},
3470   {"bfext",   2,  0x08,  bfe_reg_reg_imm, 0},
3471   {"bfext.b", 2,  0x08,  bfe_reg_opr_reg, 0},
3472   {"bfext.w", 2,  0x08,  bfe_reg_opr_reg, 0},
3473   {"bfext.p", 2,  0x08,  bfe_reg_opr_reg, 0},
3474   {"bfext.l", 2,  0x08,  bfe_reg_opr_reg, 0},
3475   {"bfext.b", 2,  0x08,  bfe_opr_reg_reg, 0},
3476   {"bfext.w", 2,  0x08,  bfe_opr_reg_reg, 0},
3477   {"bfext.p", 2,  0x08,  bfe_opr_reg_reg, 0},
3478   {"bfext.l", 2,  0x08,  bfe_opr_reg_reg, 0},
3479   {"bfext.b", 2,  0x08,  bfe_reg_opr_imm, 0},
3480   {"bfext.w", 2,  0x08,  bfe_reg_opr_imm, 0},
3481   {"bfext.p", 2,  0x08,  bfe_reg_opr_imm, 0},
3482   {"bfext.l", 2,  0x08,  bfe_reg_opr_imm, 0},
3483   {"bfext.b", 2,  0x08,  bfe_opr_reg_imm, 0},
3484   {"bfext.w", 2,  0x08,  bfe_opr_reg_imm, 0},
3485   {"bfext.p", 2,  0x08,  bfe_opr_reg_imm, 0},
3486   {"bfext.l", 2,  0x08,  bfe_opr_reg_imm, 0},
3487 
3488 
3489   {"bfins",   2,  0x08,  bfi_reg_reg_reg, 0},
3490   {"bfins",   2,  0x08,  bfi_reg_reg_imm, 0},
3491   {"bfins.b", 2,  0x08,  bfi_reg_opr_reg, 0},
3492   {"bfins.w", 2,  0x08,  bfi_reg_opr_reg, 0},
3493   {"bfins.p", 2,  0x08,  bfi_reg_opr_reg, 0},
3494   {"bfins.l", 2,  0x08,  bfi_reg_opr_reg, 0},
3495   {"bfins.b", 2,  0x08,  bfi_opr_reg_reg, 0},
3496   {"bfins.w", 2,  0x08,  bfi_opr_reg_reg, 0},
3497   {"bfins.p", 2,  0x08,  bfi_opr_reg_reg, 0},
3498   {"bfins.l", 2,  0x08,  bfi_opr_reg_reg, 0},
3499   {"bfins.b", 2,  0x08,  bfi_reg_opr_imm, 0},
3500   {"bfins.w", 2,  0x08,  bfi_reg_opr_imm, 0},
3501   {"bfins.p", 2,  0x08,  bfi_reg_opr_imm, 0},
3502   {"bfins.l", 2,  0x08,  bfi_reg_opr_imm, 0},
3503   {"bfins.b", 2,  0x08,  bfi_opr_reg_imm, 0},
3504   {"bfins.w", 2,  0x08,  bfi_opr_reg_imm, 0},
3505   {"bfins.p", 2,  0x08,  bfi_opr_reg_imm, 0},
3506   {"bfins.l", 2,  0x08,  bfi_opr_reg_imm, 0},
3507 
3508 
3509   {"minu",  2,  0x10,  regd_opr, 0},
3510   {"maxu",  2,  0x18,  regd_opr, 0},
3511   {"mins",  2,  0x20,  regd_opr, 0},
3512   {"maxs",  2,  0x28,  regd_opr, 0},
3513 
3514   {"clb",   2,  0x91,  tfr, 0},
3515 
3516   {"trap",  2,  0x00, trap_imm, 0},
3517   {"abs",   2,  0x40, reg_inh, 0},
3518   {"sat",   2,  0xa0, reg_inh, 0},
3519 
3520   {"rti",   2,  0x90, no_operands, 0},
3521   {"stop",  2,  0x05, no_operands, 0},
3522   {"wai",   2,  0x06, no_operands, 0},
3523   {"sys",   2,  0x07, no_operands, 0},
3524 
3525   {"bit",   2,   0x58,  regd_imm, 0},
3526   {"bit",   2,   0x68,  regd_opr, 0},
3527 
3528   {"adc",   2,   0x50,  regd_imm, 0},
3529   {"adc",   2,   0x60,  regd_opr, 0},
3530 
3531   {"sbc",   2,   0x70,  regd_imm, 0},
3532   {"eor",   2,   0x78,  regd_imm, 0},
3533 
3534   {"sbc",   2,   0x80,  regd_opr, 0},
3535   {"eor",   2,   0x88,  regd_opr, 0},
3536 
3537   {"divs",   2,  0x30,  mul_reg_reg_reg, 0},
3538   {"divu",   2,  0x30,  mul_reg_reg_reg, 0},
3539 
3540   {"divs.b", 2,  0x30,  mul_reg_reg_opr, 0},
3541   {"divs.w", 2,  0x30,  mul_reg_reg_opr, 0},
3542   {"divs.l", 2,  0x30,  mul_reg_reg_opr, 0},
3543 
3544   {"divu.b", 2,  0x30,  mul_reg_reg_opr, 0},
3545   {"divu.w", 2,  0x30,  mul_reg_reg_opr, 0},
3546   {"divu.l", 2,  0x30,  mul_reg_reg_opr, 0},
3547 
3548   {"divs.b", 2,  0x30,  mul_reg_reg_imm, 0},
3549   {"divs.w", 2,  0x30,  mul_reg_reg_imm, 0},
3550   {"divs.l", 2,  0x30,  mul_reg_reg_imm, 0},
3551 
3552   {"divu.b", 2,  0x30,  mul_reg_reg_imm, 0},
3553   {"divu.w", 2,  0x30,  mul_reg_reg_imm, 0},
3554   {"divu.l", 2,  0x30,  mul_reg_reg_imm, 0},
3555 
3556   {"divs.bb", 2,  0x30,  mul_reg_opr_opr, 0},
3557   {"divs.bw", 2,  0x30,  mul_reg_opr_opr, 0},
3558   {"divs.bp", 2,  0x30,  mul_reg_opr_opr, 0},
3559   {"divs.bl", 2,  0x30,  mul_reg_opr_opr, 0},
3560 
3561   {"divs.wb", 2,  0x30,  mul_reg_opr_opr, 0},
3562   {"divs.ww", 2,  0x30,  mul_reg_opr_opr, 0},
3563   {"divs.wp", 2,  0x30,  mul_reg_opr_opr, 0},
3564   {"divs.wl", 2,  0x30,  mul_reg_opr_opr, 0},
3565 
3566   {"divs.pb", 2,  0x30,  mul_reg_opr_opr, 0},
3567   {"divs.pw", 2,  0x30,  mul_reg_opr_opr, 0},
3568   {"divs.pp", 2,  0x30,  mul_reg_opr_opr, 0},
3569   {"divs.pl", 2,  0x30,  mul_reg_opr_opr, 0},
3570 
3571   {"divs.lb", 2,  0x30,  mul_reg_opr_opr, 0},
3572   {"divs.lw", 2,  0x30,  mul_reg_opr_opr, 0},
3573   {"divs.lp", 2,  0x30,  mul_reg_opr_opr, 0},
3574   {"divs.ll", 2,  0x30,  mul_reg_opr_opr, 0},
3575 
3576   {"divu.bb", 2,  0x30,  mul_reg_opr_opr, 0},
3577   {"divu.bw", 2,  0x30,  mul_reg_opr_opr, 0},
3578   {"divu.bp", 2,  0x30,  mul_reg_opr_opr, 0},
3579   {"divu.bl", 2,  0x30,  mul_reg_opr_opr, 0},
3580 
3581   {"divu.wb", 2,  0x30,  mul_reg_opr_opr, 0},
3582   {"divu.ww", 2,  0x30,  mul_reg_opr_opr, 0},
3583   {"divu.wp", 2,  0x30,  mul_reg_opr_opr, 0},
3584   {"divu.wl", 2,  0x30,  mul_reg_opr_opr, 0},
3585 
3586   {"divu.pb", 2,  0x30,  mul_reg_opr_opr, 0},
3587   {"divu.pw", 2,  0x30,  mul_reg_opr_opr, 0},
3588   {"divu.pp", 2,  0x30,  mul_reg_opr_opr, 0},
3589   {"divu.pl", 2,  0x30,  mul_reg_opr_opr, 0},
3590 
3591   {"divu.lb", 2,  0x30,  mul_reg_opr_opr, 0},
3592   {"divu.lw", 2,  0x30,  mul_reg_opr_opr, 0},
3593   {"divu.lp", 2,  0x30,  mul_reg_opr_opr, 0},
3594   {"divu.ll", 2,  0x30,  mul_reg_opr_opr, 0},
3595 
3596   {"qmuls",   2,  0xb0,  mul_reg_reg_reg, 0},
3597   {"qmulu",   2,  0xb0,  mul_reg_reg_reg, 0},
3598 
3599   {"qmuls.b", 2,  0xb0,  mul_reg_reg_opr, 0},
3600   {"qmuls.w", 2,  0xb0,  mul_reg_reg_opr, 0},
3601   {"qmuls.l", 2,  0xb0,  mul_reg_reg_opr, 0},
3602 
3603   {"qmulu.b", 2,  0xb0,  mul_reg_reg_opr, 0},
3604   {"qmulu.w", 2,  0xb0,  mul_reg_reg_opr, 0},
3605   {"qmulu.l", 2,  0xb0,  mul_reg_reg_opr, 0},
3606 
3607   {"qmuls.b", 2,  0xb0,  mul_reg_reg_imm, 0},
3608   {"qmuls.w", 2,  0xb0,  mul_reg_reg_imm, 0},
3609   {"qmuls.l", 2,  0xb0,  mul_reg_reg_imm, 0},
3610 
3611   {"qmulu.b", 2,  0xb0,  mul_reg_reg_imm, 0},
3612   {"qmulu.w", 2,  0xb0,  mul_reg_reg_imm, 0},
3613   {"qmulu.l", 2,  0xb0,  mul_reg_reg_imm, 0},
3614 
3615   {"qmuls.bb", 2,  0xb0,  mul_reg_opr_opr, 0},
3616   {"qmuls.bw", 2,  0xb0,  mul_reg_opr_opr, 0},
3617   {"qmuls.bp", 2,  0xb0,  mul_reg_opr_opr, 0},
3618   {"qmuls.bl", 2,  0xb0,  mul_reg_opr_opr, 0},
3619 
3620   {"qmuls.wb", 2,  0xb0,  mul_reg_opr_opr, 0},
3621   {"qmuls.ww", 2,  0xb0,  mul_reg_opr_opr, 0},
3622   {"qmuls.wp", 2,  0xb0,  mul_reg_opr_opr, 0},
3623   {"qmuls.wl", 2,  0xb0,  mul_reg_opr_opr, 0},
3624 
3625   {"qmuls.pb", 2,  0xb0,  mul_reg_opr_opr, 0},
3626   {"qmuls.pw", 2,  0xb0,  mul_reg_opr_opr, 0},
3627   {"qmuls.pp", 2,  0xb0,  mul_reg_opr_opr, 0},
3628   {"qmuls.pl", 2,  0xb0,  mul_reg_opr_opr, 0},
3629 
3630   {"qmuls.lb", 2,  0xb0,  mul_reg_opr_opr, 0},
3631   {"qmuls.lw", 2,  0xb0,  mul_reg_opr_opr, 0},
3632   {"qmuls.lp", 2,  0xb0,  mul_reg_opr_opr, 0},
3633   {"qmuls.ll", 2,  0xb0,  mul_reg_opr_opr, 0},
3634 
3635   {"qmulu.bb", 2,  0xb0,  mul_reg_opr_opr, 0},
3636   {"qmulu.bw", 2,  0xb0,  mul_reg_opr_opr, 0},
3637   {"qmulu.bp", 2,  0xb0,  mul_reg_opr_opr, 0},
3638   {"qmulu.bl", 2,  0xb0,  mul_reg_opr_opr, 0},
3639 
3640   {"qmulu.wb", 2,  0xb0,  mul_reg_opr_opr, 0},
3641   {"qmulu.ww", 2,  0xb0,  mul_reg_opr_opr, 0},
3642   {"qmulu.wp", 2,  0xb0,  mul_reg_opr_opr, 0},
3643   {"qmulu.wl", 2,  0xb0,  mul_reg_opr_opr, 0},
3644 
3645   {"qmulu.pb", 2,  0xb0,  mul_reg_opr_opr, 0},
3646   {"qmulu.pw", 2,  0xb0,  mul_reg_opr_opr, 0},
3647   {"qmulu.pp", 2,  0xb0,  mul_reg_opr_opr, 0},
3648   {"qmulu.pl", 2,  0xb0,  mul_reg_opr_opr, 0},
3649 
3650   {"qmulu.lb", 2,  0xb0,  mul_reg_opr_opr, 0},
3651   {"qmulu.lw", 2,  0xb0,  mul_reg_opr_opr, 0},
3652   {"qmulu.lp", 2,  0xb0,  mul_reg_opr_opr, 0},
3653   {"qmulu.ll", 2,  0xb0,  mul_reg_opr_opr, 0},
3654 
3655   {"macs",   2,  0x48,  mul_reg_reg_reg, 0},
3656   {"macu",   2,  0x48,  mul_reg_reg_reg, 0},
3657 
3658   {"macs.b", 2,  0x48,  mul_reg_reg_opr, 0},
3659   {"macs.w", 2,  0x48,  mul_reg_reg_opr, 0},
3660   {"macs.l", 2,  0x48,  mul_reg_reg_opr, 0},
3661 
3662   {"macu.b", 2,  0x48,  mul_reg_reg_opr, 0},
3663   {"macu.w", 2,  0x48,  mul_reg_reg_opr, 0},
3664   {"macu.l", 2,  0x48,  mul_reg_reg_opr, 0},
3665 
3666   {"macs.b", 2,  0x48,  mul_reg_reg_imm, 0},
3667   {"macs.w", 2,  0x48,  mul_reg_reg_imm, 0},
3668   {"macs.l", 2,  0x48,  mul_reg_reg_imm, 0},
3669 
3670   {"macu.b", 2,  0x48,  mul_reg_reg_imm, 0},
3671   {"macu.w", 2,  0x48,  mul_reg_reg_imm, 0},
3672   {"macu.l", 2,  0x48,  mul_reg_reg_imm, 0},
3673 
3674   {"macs.bb", 2,  0x48,  mul_reg_opr_opr, 0},
3675   {"macs.bw", 2,  0x48,  mul_reg_opr_opr, 0},
3676   {"macs.bp", 2,  0x48,  mul_reg_opr_opr, 0},
3677   {"macs.bl", 2,  0x48,  mul_reg_opr_opr, 0},
3678 
3679   {"macs.wb", 2,  0x48,  mul_reg_opr_opr, 0},
3680   {"macs.ww", 2,  0x48,  mul_reg_opr_opr, 0},
3681   {"macs.wp", 2,  0x48,  mul_reg_opr_opr, 0},
3682   {"macs.wl", 2,  0x48,  mul_reg_opr_opr, 0},
3683 
3684   {"macs.pb", 2,  0x48,  mul_reg_opr_opr, 0},
3685   {"macs.pw", 2,  0x48,  mul_reg_opr_opr, 0},
3686   {"macs.pp", 2,  0x48,  mul_reg_opr_opr, 0},
3687   {"macs.pl", 2,  0x48,  mul_reg_opr_opr, 0},
3688 
3689   {"macs.lb", 2,  0x48,  mul_reg_opr_opr, 0},
3690   {"macs.lw", 2,  0x48,  mul_reg_opr_opr, 0},
3691   {"macs.lp", 2,  0x48,  mul_reg_opr_opr, 0},
3692   {"macs.ll", 2,  0x48,  mul_reg_opr_opr, 0},
3693 
3694   {"macu.bb", 2,  0x48,  mul_reg_opr_opr, 0},
3695   {"macu.bw", 2,  0x48,  mul_reg_opr_opr, 0},
3696   {"macu.bp", 2,  0x48,  mul_reg_opr_opr, 0},
3697   {"macu.bl", 2,  0x48,  mul_reg_opr_opr, 0},
3698 
3699   {"macu.wb", 2,  0x48,  mul_reg_opr_opr, 0},
3700   {"macu.ww", 2,  0x48,  mul_reg_opr_opr, 0},
3701   {"macu.wp", 2,  0x48,  mul_reg_opr_opr, 0},
3702   {"macu.wl", 2,  0x48,  mul_reg_opr_opr, 0},
3703 
3704   {"macu.pb", 2,  0x48,  mul_reg_opr_opr, 0},
3705   {"macu.pw", 2,  0x48,  mul_reg_opr_opr, 0},
3706   {"macu.pp", 2,  0x48,  mul_reg_opr_opr, 0},
3707   {"macu.pl", 2,  0x48,  mul_reg_opr_opr, 0},
3708 
3709   {"macu.lb", 2,  0x48,  mul_reg_opr_opr, 0},
3710   {"macu.lw", 2,  0x48,  mul_reg_opr_opr, 0},
3711   {"macu.lp", 2,  0x48,  mul_reg_opr_opr, 0},
3712   {"macu.ll", 2,  0x48,  mul_reg_opr_opr, 0},
3713 
3714   {"mods",   2,  0x38,  mul_reg_reg_reg, 0},
3715   {"modu",   2,  0x38,  mul_reg_reg_reg, 0},
3716 
3717   {"mods.b", 2,  0x38,  mul_reg_reg_opr, 0},
3718   {"mods.w", 2,  0x38,  mul_reg_reg_opr, 0},
3719   {"mods.l", 2,  0x38,  mul_reg_reg_opr, 0},
3720 
3721   {"modu.b", 2,  0x38,  mul_reg_reg_opr, 0},
3722   {"modu.w", 2,  0x38,  mul_reg_reg_opr, 0},
3723   {"modu.l", 2,  0x38,  mul_reg_reg_opr, 0},
3724 
3725   {"mods.b", 2,  0x38,  mul_reg_reg_imm, 0},
3726   {"mods.w", 2,  0x38,  mul_reg_reg_imm, 0},
3727   {"mods.l", 2,  0x38,  mul_reg_reg_imm, 0},
3728 
3729   {"modu.b", 2,  0x38,  mul_reg_reg_imm, 0},
3730   {"modu.w", 2,  0x38,  mul_reg_reg_imm, 0},
3731   {"modu.l", 2,  0x38,  mul_reg_reg_imm, 0},
3732 
3733   {"mods.bb", 2,  0x38,  mul_reg_opr_opr, 0},
3734   {"mods.bw", 2,  0x38,  mul_reg_opr_opr, 0},
3735   {"mods.bp", 2,  0x38,  mul_reg_opr_opr, 0},
3736   {"mods.bl", 2,  0x38,  mul_reg_opr_opr, 0},
3737 
3738   {"mods.wb", 2,  0x38,  mul_reg_opr_opr, 0},
3739   {"mods.ww", 2,  0x38,  mul_reg_opr_opr, 0},
3740   {"mods.wp", 2,  0x38,  mul_reg_opr_opr, 0},
3741   {"mods.wl", 2,  0x38,  mul_reg_opr_opr, 0},
3742 
3743   {"mods.pb", 2,  0x38,  mul_reg_opr_opr, 0},
3744   {"mods.pw", 2,  0x38,  mul_reg_opr_opr, 0},
3745   {"mods.pp", 2,  0x38,  mul_reg_opr_opr, 0},
3746   {"mods.pl", 2,  0x38,  mul_reg_opr_opr, 0},
3747 
3748   {"mods.lb", 2,  0x38,  mul_reg_opr_opr, 0},
3749   {"mods.lw", 2,  0x38,  mul_reg_opr_opr, 0},
3750   {"mods.lp", 2,  0x38,  mul_reg_opr_opr, 0},
3751   {"mods.ll", 2,  0x38,  mul_reg_opr_opr, 0},
3752 
3753   {"modu.bb", 2,  0x38,  mul_reg_opr_opr, 0},
3754   {"modu.bw", 2,  0x38,  mul_reg_opr_opr, 0},
3755   {"modu.bp", 2,  0x38,  mul_reg_opr_opr, 0},
3756   {"modu.bl", 2,  0x38,  mul_reg_opr_opr, 0},
3757 
3758   {"modu.wb", 2,  0x38,  mul_reg_opr_opr, 0},
3759   {"modu.ww", 2,  0x38,  mul_reg_opr_opr, 0},
3760   {"modu.wp", 2,  0x38,  mul_reg_opr_opr, 0},
3761   {"modu.wl", 2,  0x38,  mul_reg_opr_opr, 0},
3762 
3763   {"modu.pb", 2,  0x38,  mul_reg_opr_opr, 0},
3764   {"modu.pw", 2,  0x38,  mul_reg_opr_opr, 0},
3765   {"modu.pp", 2,  0x38,  mul_reg_opr_opr, 0},
3766   {"modu.pl", 2,  0x38,  mul_reg_opr_opr, 0},
3767 
3768   {"modu.lb", 2,  0x38,  mul_reg_opr_opr, 0},
3769   {"modu.lw", 2,  0x38,  mul_reg_opr_opr, 0},
3770   {"modu.lp", 2,  0x38,  mul_reg_opr_opr, 0},
3771   {"modu.ll", 2,  0x38,  mul_reg_opr_opr, 0}
3772 };
3773 
3774 
3775 /* Gas line assembler entry point.  */
3776 
3777 /* This is the main entry point for the machine-dependent assembler.  str
3778    points to a machine-dependent instruction.  This function is supposed to
3779    emit the frags/bytes it assembles to.  */
3780 void
md_assemble(char * str)3781 md_assemble (char *str)
3782 {
3783   char *op_start;
3784   char *op_end;
3785   char name[20];
3786   size_t nlen = 0;
3787 
3788   fail_line_pointer = NULL;
3789 
3790   /* Find the opcode end and get the opcode in 'name'.  The opcode is forced
3791      lower case (the opcode table only has lower case op-codes).  */
3792   for (op_start = op_end = str;
3793        *op_end && !is_end_of_line[(int)*op_end] && *op_end != ' ';
3794        op_end++)
3795     {
3796       name[nlen] = TOLOWER (op_start[nlen]);
3797       nlen++;
3798       gas_assert (nlen < sizeof (name) - 1);
3799     }
3800   name[nlen] = 0;
3801 
3802   if (nlen == 0)
3803     {
3804       as_bad (_("No instruction or missing opcode."));
3805       return;
3806     }
3807 
3808   input_line_pointer = skip_whites (op_end);
3809 
3810   size_t i;
3811   for (i = 0; i < sizeof (opcodes) / sizeof (opcodes[0]); ++i)
3812     {
3813       const struct instruction *opc = opcodes + i;
3814       if (0 == strcmp (name, opc->name))
3815 	{
3816 	  if (opc->parse_operands (opc))
3817 	    return;
3818 	  continue;
3819 	}
3820     }
3821 
3822   as_bad (_("Invalid instruction: \"%s\""), str);
3823   as_bad (_("First invalid token: \"%s\""), fail_line_pointer);
3824   while (*input_line_pointer++)
3825     ;
3826 }
3827 
3828 
3829 
3830 
3831 
3832 /* Relocation, relaxation and frag conversions.  */
3833 
3834 /* PC-relative offsets are relative to the start of the
3835    next instruction.  That is, the address of the offset, plus its
3836    size, since the offset is always the last part of the insn.  */
3837 long
md_pcrel_from(fixS * fixP)3838 md_pcrel_from (fixS *fixP)
3839 {
3840   long ret = fixP->fx_size + fixP->fx_frag->fr_address;
3841   if (fixP->fx_addsy && S_IS_DEFINED (fixP->fx_addsy))
3842     ret += fixP->fx_where;
3843 
3844   return ret;
3845 }
3846 
3847 
3848 /* We need a port-specific relaxation function to cope with sym2 - sym1
3849    relative expressions with both symbols in the same segment (but not
3850    necessarily in the same frag as this insn), for example:
3851    ldab sym2-(sym1-2),pc
3852    sym1:
3853    The offset can be 5, 9 or 16 bits long.  */
3854 
3855 long
s12z_relax_frag(segT seg ATTRIBUTE_UNUSED,fragS * fragP ATTRIBUTE_UNUSED,long stretch ATTRIBUTE_UNUSED)3856 s12z_relax_frag (segT seg ATTRIBUTE_UNUSED, fragS *fragP ATTRIBUTE_UNUSED,
3857 		   long stretch ATTRIBUTE_UNUSED)
3858 {
3859   return 0;
3860 }
3861 
3862 void
md_convert_frag(bfd * abfd ATTRIBUTE_UNUSED,asection * sec ATTRIBUTE_UNUSED,fragS * fragP ATTRIBUTE_UNUSED)3863 md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, asection *sec ATTRIBUTE_UNUSED,
3864                  fragS *fragP ATTRIBUTE_UNUSED)
3865 {
3866 }
3867 
3868 /* On an ELF system, we can't relax a weak symbol.  The weak symbol
3869    can be overridden at final link time by a non weak symbol.  We can
3870    relax externally visible symbol because there is no shared library
3871    and such symbol can't be overridden (unless they are weak).  */
3872 
3873 /* Force truly undefined symbols to their maximum size, and generally set up
3874    the frag list to be relaxed.  */
3875 int
md_estimate_size_before_relax(fragS * fragP ATTRIBUTE_UNUSED,asection * segment ATTRIBUTE_UNUSED)3876 md_estimate_size_before_relax (fragS *fragP ATTRIBUTE_UNUSED, asection *segment ATTRIBUTE_UNUSED)
3877 {
3878   return 0;
3879 }
3880 
3881 
3882 /* If while processing a fixup, a reloc really needs to be created
3883    then it is done here.  */
3884 arelent *
tc_gen_reloc(asection * section,fixS * fixp)3885 tc_gen_reloc (asection *section, fixS *fixp)
3886 {
3887   arelent *reloc = XNEW (arelent);
3888   reloc->sym_ptr_ptr = XNEW (asymbol *);
3889   *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
3890   reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
3891   reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type);
3892   if (reloc->howto == (reloc_howto_type *) NULL)
3893     {
3894       as_bad_where (fixp->fx_file, fixp->fx_line,
3895 		    _("Relocation %d is not supported by object file format."),
3896 		    (int) fixp->fx_r_type);
3897       return NULL;
3898     }
3899 
3900   if (0 == (section->flags & SEC_CODE))
3901     reloc->addend = fixp->fx_offset;
3902   else
3903     reloc->addend = fixp->fx_addnumber;
3904 
3905   return reloc;
3906 }
3907 
3908 /* See whether we need to force a relocation into the output file.  */
3909 int
tc_s12z_force_relocation(fixS * fixP)3910 tc_s12z_force_relocation (fixS *fixP)
3911 {
3912   return generic_force_reloc (fixP);
3913 }
3914 
3915 /* Here we decide which fixups can be adjusted to make them relative
3916    to the beginning of the section instead of the symbol.  Basically
3917    we need to make sure that the linker relaxation is done
3918    correctly, so in some cases we force the original symbol to be
3919    used.  */
3920 bool
tc_s12z_fix_adjustable(fixS * fixP ATTRIBUTE_UNUSED)3921 tc_s12z_fix_adjustable (fixS *fixP ATTRIBUTE_UNUSED)
3922 {
3923   return true;
3924 }
3925 
3926 void
md_apply_fix(fixS * fixP,valueT * valP,segT seg ATTRIBUTE_UNUSED)3927 md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
3928 {
3929   long value = *valP;
3930 
3931   if (fixP->fx_addsy == (symbolS *) NULL)
3932     fixP->fx_done = 1;
3933 
3934   /* We don't actually support subtracting a symbol.  */
3935   if (fixP->fx_subsy != (symbolS *) NULL)
3936     as_bad_where (fixP->fx_file, fixP->fx_line, _("Expression too complex."));
3937 
3938   /*
3939     Patch the instruction with the resolved operand.  Elf relocation
3940     info will also be generated to take care of linker/loader fixups.
3941   */
3942   char *where = fixP->fx_frag->fr_literal + fixP->fx_where;
3943 
3944   switch (fixP->fx_r_type)
3945     {
3946     case BFD_RELOC_8:
3947       ((bfd_byte *) where)[0] = (bfd_byte) value;
3948       break;
3949     case BFD_RELOC_16:
3950       bfd_putb16 ((bfd_vma) value, (unsigned char *) where);
3951       break;
3952     case BFD_RELOC_24:
3953       bfd_putb24 ((bfd_vma) value, (unsigned char *) where);
3954       break;
3955     case BFD_RELOC_S12Z_OPR:
3956       {
3957         switch (fixP->fx_size)
3958           {
3959           case 3:
3960             bfd_putb24 ((bfd_vma) value, (unsigned char *) where);
3961             break;
3962           case 2:
3963             bfd_putb16 ((bfd_vma) value, (unsigned char *) where);
3964             break;
3965           default:
3966             abort ();
3967           }
3968       }
3969       break;
3970     case BFD_RELOC_32:
3971       bfd_putb32 ((bfd_vma) value, (unsigned char *) where);
3972       break;
3973     case BFD_RELOC_16_PCREL:
3974       if (value < -0x4000 || value > 0x3FFF)
3975 	as_bad_where (fixP->fx_file, fixP->fx_line,
3976 		      _("Value out of 16-bit range."));
3977 
3978       bfd_putb16 ((bfd_vma) value | 0x8000, (unsigned char *) where);
3979       break;
3980 
3981     default:
3982       as_fatal (_("Line %d: unknown relocation type: 0x%x."),
3983 		fixP->fx_line, fixP->fx_r_type);
3984     }
3985 }
3986 
3987 /* Set the ELF specific flags.  */
3988 void
s12z_elf_final_processing(void)3989 s12z_elf_final_processing (void)
3990 {
3991 }
3992