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