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