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