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