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