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