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