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