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