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