[gdb/build] Fix enum param_types odr violation
[binutils-gdb.git] / gas / config / tc-s12z.c
blob6bbd7a12557be51deb142b0ed03482f6a4de12cd
1 /* tc-s12z.c -- Assembler code for the Freescale S12Z
2 Copyright (C) 2018-2023 Free Software Foundation, Inc.
4 This file is part of GAS, the GNU Assembler.
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.
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.
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. */
21 #include "as.h"
22 #include "safe-ctype.h"
23 #include "subsegs.h"
24 #include "dwarf2dbg.h"
25 #include "opcode/s12z.h"
26 #include <limits.h>
28 const char comment_chars[] = ";";
30 const char line_comment_chars[] = "#*";
31 const char line_separator_chars[] = "";
33 static char * register_prefix = NULL;
35 const char EXP_CHARS[] = "eE";
36 const char FLT_CHARS[] = "dD";
38 static char *fail_line_pointer;
40 /* A wrapper around the standard library's strtol.
41 It converts STR into an integral value.
42 This wrapper deals with literal_prefix_dollar_hex. */
43 static long
44 s12z_strtol (const char *str, char ** endptr)
46 int base = 0;
47 bool negative = false;
49 long result = 0;
51 char *start = (char *) str;
53 /* In the case where literal_prefix_dollar_hex is TRUE the sign has
54 to be handled explicitly. Otherwise the string will not be
55 recognised as an integer. */
56 if (str[0] == '-')
58 negative = true;
59 ++str;
61 else if (str[0] == '+')
63 ++str;
66 if (literal_prefix_dollar_hex && (str[0] == '$'))
68 base = 16;
69 str++;
72 result = strtol (str, endptr, base);
73 if (*endptr == str)
75 *endptr = start;
77 if (negative)
78 result = -result;
80 return result;
85 /* Options and initialization. */
87 const char *md_shortopts = "";
89 struct option md_longopts[] =
91 #define OPTION_REG_PREFIX (OPTION_MD_BASE)
92 {"mreg-prefix", required_argument, NULL, OPTION_REG_PREFIX},
93 #define OPTION_DOLLAR_HEX (OPTION_MD_BASE + 1)
94 {"mdollar-hex", no_argument, NULL, OPTION_DOLLAR_HEX},
95 {NULL, no_argument, NULL, 0}
98 size_t md_longopts_size = sizeof (md_longopts);
101 relax_typeS md_relax_table[] =
106 /* This table describes all the machine specific pseudo-ops the assembler
107 has to support. The fields are:
108 pseudo-op name without dot
109 function to call to execute this pseudo-op
110 Integer arg to pass to the function. */
111 const pseudo_typeS md_pseudo_table[] =
113 {0, 0, 0}
117 /* Get the target cpu for the assembler. */
118 const char *
119 s12z_arch_format (void)
121 return "elf32-s12z";
124 enum bfd_architecture
125 s12z_arch (void)
127 return bfd_arch_s12z;
131 s12z_mach (void)
133 return 0;
136 /* Listing header selected according to cpu. */
137 const char *
138 s12z_listing_header (void)
140 return "S12Z GAS ";
143 void
144 md_show_usage (FILE *stream)
146 fputs (_("\ns12z options:\n"), stream);
147 fputs (_(" -mreg-prefix=PREFIX set a prefix used to indicate register names (default none)\n"), stream);
148 fputs (_(" -mdollar-hex the prefix '$' instead of '0x' is used to indicate literal hexadecimal constants\n"), stream);
151 void
152 s12z_print_statistics (FILE *file ATTRIBUTE_UNUSED)
157 md_parse_option (int c, const char *arg)
159 switch (c)
161 case OPTION_REG_PREFIX:
162 register_prefix = xstrdup (arg);
163 break;
164 case OPTION_DOLLAR_HEX:
165 literal_prefix_dollar_hex = true;
166 break;
167 default:
168 return 0;
170 return 1;
173 symbolS *
174 md_undefined_symbol (char *name ATTRIBUTE_UNUSED)
176 return 0;
179 const char *
180 md_atof (int type, char *litP, int *sizeP)
182 return ieee_md_atof (type, litP, sizeP, true);
185 valueT
186 md_section_align (asection *seg, valueT addr)
188 int align = bfd_section_alignment (seg);
189 return ((addr + (1 << align) - 1) & -(1 << align));
192 void
193 md_begin (void)
197 void
198 s12z_init_after_args (void)
200 if (flag_traditional_format)
201 literal_prefix_dollar_hex = true;
204 /* Builtin help. */
207 static char *
208 skip_whites (char *p)
210 while (*p == ' ' || *p == '\t')
211 p++;
213 return p;
218 /* Start a new insn that contains at least 'size' bytes. Record the
219 line information of that insn in the dwarf2 debug sections. */
220 static char *
221 s12z_new_insn (int size)
223 char *f = frag_more (size);
225 dwarf2_emit_insn (size);
227 return f;
232 static bool lex_reg_name (uint16_t which, int *reg);
234 static bool
235 lex_constant (long *v)
237 char *end = NULL;
238 char *p = input_line_pointer;
240 /* A constant may not have the same value as a register
241 eg: "d6" */
242 int dummy;
243 if (lex_reg_name (~0, &dummy))
245 input_line_pointer = p;
246 return false;
249 errno = 0;
250 *v = s12z_strtol (p, &end);
251 if (errno == 0 && end != p)
253 input_line_pointer = end;
254 return true;
257 return false;
260 static bool
261 lex_match (char x)
263 char *p = input_line_pointer;
264 if (*p != x)
265 return false;
267 input_line_pointer++;
268 return true;
272 static bool
273 lex_expression (expressionS *exp)
275 char *ilp = input_line_pointer;
276 int dummy;
277 exp->X_op = O_absent;
279 if (lex_match ('#'))
280 goto fail;
282 if (lex_reg_name (~0, &dummy))
283 goto fail;
285 expression (exp);
286 if (exp->X_op != O_absent)
287 return true;
289 fail:
290 fail_line_pointer = input_line_pointer;
291 input_line_pointer = ilp;
292 return false;
295 /* Immediate operand.
296 If EXP_O is non-null, then a symbolic expression is permitted,
297 in which case, EXP_O will be populated with the parsed expression.
299 static bool
300 lex_imm (long *v, expressionS *exp_o)
302 char *ilp = input_line_pointer;
304 if (*input_line_pointer != '#')
305 goto fail;
307 input_line_pointer++;
308 expressionS exp;
309 if (!lex_expression (&exp))
310 goto fail;
312 if (exp.X_op != O_constant)
314 if (!exp_o)
315 as_bad (_("A non-constant expression is not permitted here"));
316 else
317 *exp_o = exp;
320 *v = exp.X_add_number;
321 return true;
323 fail:
324 fail_line_pointer = input_line_pointer;
325 input_line_pointer = ilp;
326 return false;
329 /* Short mmediate operand */
330 static bool
331 lex_imm_e4 (long *val)
333 char *ilp = input_line_pointer;
334 if ((lex_imm (val, NULL)))
336 if ((*val == -1) || (*val > 0 && *val <= 15))
338 return true;
341 fail_line_pointer = input_line_pointer;
342 input_line_pointer = ilp;
343 return false;
346 static bool
347 lex_match_string (const char *s)
349 char *p = input_line_pointer;
350 while (p != 0 && *p != '\t' && *p != ' ' && *p != '\0')
352 p++;
355 size_t len = p - input_line_pointer;
356 if (len != strlen (s))
357 return false;
359 if (0 == strncasecmp (s, input_line_pointer, len))
361 input_line_pointer = p;
362 return true;
365 return false;
368 /* Parse a register name.
369 WHICH is a ORwise combination of the registers which are accepted.
370 ~0 accepts all.
371 On success, REG will be filled with the index of the register which
372 was successfully scanned.
374 static bool
375 lex_reg_name (uint16_t which, int *reg)
377 char *p = input_line_pointer;
379 if (p == 0)
380 return false;
382 /* Scan (and ignore) the register prefix. */
383 if (register_prefix)
385 int len = strlen (register_prefix);
386 if (0 == strncmp (register_prefix, p, len))
387 p += len;
388 else
389 return false;
392 char *start_of_reg_name = p;
394 while ((*p >= 'a' && *p <='z')
395 || (*p >= '0' && *p <= '9')
396 || (*p >= 'A' && *p <='Z'))
398 p++;
401 size_t len = p - start_of_reg_name;
403 if (len <= 0)
404 return false;
406 int i;
407 for (i = 0; i < S12Z_N_REGISTERS; ++i)
409 gas_assert (registers[i].name);
411 if (len == strlen (registers[i].name)
412 && 0 == strncasecmp (registers[i].name, start_of_reg_name, len))
414 if ((0x1U << i) & which)
416 input_line_pointer = p;
417 *reg = i;
418 return true;
423 return false;
426 static bool
427 lex_force_match (char x)
429 char *p = input_line_pointer;
430 if (*p != x)
432 as_bad (_("Expecting '%c'"), x);
433 return false;
436 input_line_pointer++;
437 return true;
440 static bool
441 lex_opr (uint8_t *buffer, int *n_bytes, expressionS *exp,
442 bool immediate_ok)
444 char *ilp = input_line_pointer;
445 uint8_t *xb = buffer;
446 int reg;
447 long imm;
448 exp->X_op = O_absent;
449 *n_bytes = 0;
450 *xb = 0;
451 if (lex_imm_e4 (&imm))
453 if (!immediate_ok)
455 as_bad (_("An immediate value in a source operand is inappropriate"));
456 return false;
458 if (imm > 0)
459 *xb = imm;
460 else
461 *xb = 0;
462 *xb |= 0x70;
463 *n_bytes = 1;
464 return true;
466 else if (lex_reg_name (REG_BIT_Dn, &reg))
468 *xb = reg;
469 *xb |= 0xb8;
470 *n_bytes = 1;
471 return true;
473 else if (lex_match ('['))
475 if (lex_expression (exp))
477 long c = exp->X_add_number;
478 if (lex_match (','))
480 if (lex_reg_name (REG_BIT_XYSP, &reg))
482 int i;
483 if (c <= 255 && c >= -256)
485 *n_bytes = 2;
486 *xb |= 0xc4;
488 else
490 *n_bytes = 4;
491 *xb |= 0xc6;
493 *xb |= (reg - REG_X) << 4;
495 if (c < 0)
496 *xb |= 0x01;
497 for (i = 1; i < *n_bytes ; ++i)
499 buffer[i] = c >> (8 * (*n_bytes - i - 1));
502 else
504 as_bad (_("Bad operand for constant offset"));
505 goto fail;
508 else
510 *xb = 0xfe;
511 *n_bytes = 4;
512 buffer[1] = c >> 16;
513 buffer[2] = c >> 8;
514 buffer[3] = c;
517 else if (lex_reg_name (REG_BIT_Dn, &reg))
519 if (!lex_force_match (','))
520 goto fail;
522 int reg2;
523 if (lex_reg_name (REG_BIT_XY, &reg2))
525 *n_bytes = 1;
526 *xb = reg;
527 *xb |= (reg2 - REG_X) << 4;
528 *xb |= 0xc8;
530 else
532 as_bad (_("Invalid operand for register offset"));
533 goto fail;
536 else
538 goto fail;
540 if (!lex_force_match (']'))
541 goto fail;
542 return true;
544 else if (lex_match ('('))
546 long c;
547 if (lex_constant (&c))
549 if (!lex_force_match (','))
550 goto fail;
551 int reg2;
552 if (lex_reg_name (REG_BIT_XYSP, &reg2))
554 if (reg2 != REG_P && c >= 0 && c <= 15)
556 *n_bytes = 1;
557 *xb = 0x40;
558 *xb |= (reg2 - REG_X) << 4;
559 *xb |= c;
561 else if (c >= -256 && c <= 255)
563 *n_bytes = 2;
564 *xb = 0xc0;
565 *xb |= (reg2 - REG_X) << 4;
566 if (c < 0)
567 *xb |= 0x01;
568 buffer[1] = c;
570 else
572 *n_bytes = 4;
573 *xb = 0xc2;
574 *xb |= (reg2 - REG_X) << 4;
575 buffer[1] = c >> 16;
576 buffer[2] = c >> 8;
577 buffer[3] = c;
580 else if (lex_reg_name (REG_BIT_Dn, &reg2))
582 if (c >= -1 * (long) (0x1u << 17)
584 c < (long) (0x1u << 17) - 1)
586 *n_bytes = 3;
587 *xb = 0x80;
588 *xb |= reg2;
589 *xb |= ((c >> 16) & 0x03) << 4;
590 buffer[1] = c >> 8;
591 buffer[2] = c;
593 else
595 *n_bytes = 4;
596 *xb = 0xe8;
597 *xb |= reg2;
598 buffer[1] = c >> 16;
599 buffer[2] = c >> 8;
600 buffer[3] = c;
603 else
605 as_bad (_("Bad operand for constant offset"));
606 goto fail;
609 else if (lex_reg_name (REG_BIT_Dn, &reg))
611 if (lex_match (','))
613 int reg2;
614 if (lex_reg_name (REG_BIT_XYS, &reg2))
616 *n_bytes = 1;
617 *xb = 0x88;
618 *xb |= (reg2 - REG_X) << 4;
619 *xb |= reg;
621 else
623 as_bad (_("Invalid operand for register offset"));
624 goto fail;
627 else
629 goto fail;
632 else if (lex_reg_name (REG_BIT_XYS, &reg))
634 if (lex_match ('-'))
636 if (reg == REG_S)
638 as_bad (_("Invalid register for postdecrement operation"));
639 goto fail;
641 *n_bytes = 1;
642 if (reg == REG_X)
643 *xb = 0xc7;
644 else if (reg == REG_Y)
645 *xb = 0xd7;
647 else if (lex_match ('+'))
649 *n_bytes = 1;
650 if (reg == REG_X)
651 *xb = 0xe7;
652 else if (reg == REG_Y)
653 *xb = 0xf7;
654 else if (reg == REG_S)
655 *xb = 0xff;
657 else
659 goto fail;
662 else if (lex_match ('+'))
664 if (lex_reg_name (REG_BIT_XY, &reg))
666 *n_bytes = 1;
667 if (reg == REG_X)
668 *xb = 0xe3;
669 else if (reg == REG_Y)
670 *xb = 0xf3;
672 else
674 as_bad (_("Invalid register for preincrement operation"));
675 goto fail;
678 else if (lex_match ('-'))
680 if (lex_reg_name (REG_BIT_XYS, &reg))
682 *n_bytes = 1;
683 if (reg == REG_X)
684 *xb = 0xc3;
685 else if (reg == REG_Y)
686 *xb = 0xd3;
687 else if (reg == REG_S)
688 *xb = 0xfb;
690 else
692 as_bad (_("Invalid register for predecrement operation"));
693 goto fail;
696 else
698 goto fail;
701 if (! lex_match (')'))
702 goto fail;
703 return true;
705 else if (lex_expression (exp))
707 *xb = 0xfa;
708 *n_bytes = 4;
709 buffer[1] = 0;
710 buffer[2] = 0;
711 buffer[3] = 0;
712 if (exp->X_op == O_constant)
714 valueT value = exp->X_add_number;
716 if (value < (0x1U << 14))
718 *xb = 0x00;
719 *n_bytes = 2;
720 *xb |= value >> 8;
721 buffer[1] = value;
723 else if (value < (0x1U << 19))
725 *xb = 0xf8;
726 if (value & (0x1U << 17))
727 *xb |= 0x04;
728 if (value & (0x1U << 16))
729 *xb |= 0x01;
730 *n_bytes = 3;
731 buffer[1] = value >> 8;
732 buffer[2] = value;
734 else
736 *xb = 0xfa;
737 *n_bytes = 4;
738 buffer[1] = value >> 16;
739 buffer[2] = value >> 8;
740 buffer[3] = value;
743 return true;
746 fail:
747 fail_line_pointer = input_line_pointer;
748 input_line_pointer = ilp;
749 return false;
752 static bool
753 lex_offset (long *val)
755 char *end = NULL;
756 char *p = input_line_pointer;
758 if (*p++ != '*')
759 return false;
761 if (*p != '+' && *p != '-')
762 return false;
764 bool negative = (*p == '-');
765 p++;
767 errno = 0;
768 *val = s12z_strtol (p, &end);
769 if (errno == 0)
771 if (negative)
772 *val *= -1;
773 input_line_pointer = end;
774 return true;
777 return false;
782 struct instruction;
784 typedef bool (*parse_operand_func) (const struct instruction *);
786 struct instruction
788 const char *name;
790 /* The "page" to which the instruction belongs.
791 This is also only a hint. Some instructions might have modes in both
792 pages... */
793 char page;
795 /* This is a hint - and only a hint - about the opcode of the instruction.
796 The parse_operand_func is free to ignore it.
798 uint8_t opc;
800 parse_operand_func parse_operands;
802 /* Some instructions can be encoded with a different opcode */
803 uint8_t alt_opc;
806 static bool
807 no_operands (const struct instruction *insn)
809 if (*input_line_pointer != '\0')
811 as_bad (_("Garbage at end of instruction"));
812 return false;
815 char *f = s12z_new_insn (insn->page);
816 if (insn->page == 2)
817 number_to_chars_bigendian (f++, PAGE2_PREBYTE, 1);
819 number_to_chars_bigendian (f++, insn->opc, 1);
821 return true;
825 static void
826 emit_reloc (expressionS *exp, char *f, int size, enum bfd_reloc_code_real reloc)
828 if (exp->X_op != O_absent && exp->X_op != O_constant)
830 fixS *fix = fix_new_exp (frag_now,
831 f - frag_now->fr_literal,
832 size,
833 exp,
834 false,
835 reloc);
836 /* Some third party tools seem to use the lower bits
837 of this addend for flags. They don't get added
838 to the final location. The purpose of these flags
839 is not known. We simply set it to zero. */
840 fix->fx_addnumber = 0x00;
844 /* Emit the code for an OPR address mode operand */
845 static char *
846 emit_opr (char *f, const uint8_t *buffer, int n_bytes, expressionS *exp)
848 int i;
849 number_to_chars_bigendian (f++, buffer[0], 1);
851 emit_reloc (exp, f, 3, BFD_RELOC_S12Z_OPR);
853 for (i = 1; i < n_bytes; ++i)
854 number_to_chars_bigendian (f++, buffer[i], 1);
856 return f;
859 /* Emit the code for a 24 bit direct address operand */
860 static char *
861 emit_ext24 (char *f, long v)
863 number_to_chars_bigendian (f, v, 3);
865 return f + 3;
868 static bool
869 opr (const struct instruction *insn)
871 uint8_t buffer[4];
872 int n_bytes;
873 expressionS exp;
874 if (lex_opr (buffer, &n_bytes, &exp, false))
876 /* Large constant direct values are more efficiently encoded as ext24 mode.
877 Otherwise a decision has to be deferred to a relax. */
878 if (exp.X_op == O_constant
879 && buffer[0] == 0xFA
880 && insn->alt_opc != 0)
882 char *f = s12z_new_insn (4);
884 /* I don't think there are any instances of page 2 opcodes in this case */
885 gas_assert (insn->page == 1);
887 number_to_chars_bigendian (f++, insn->alt_opc, 1);
889 emit_ext24 (f, exp.X_add_number);
891 else
893 char *f = s12z_new_insn (n_bytes + 1);
894 number_to_chars_bigendian (f++, insn->opc, 1);
896 emit_opr (f, buffer, n_bytes, &exp);
898 return true;
901 return false;
904 /* Parse a 15 bit offset, as an expression.
905 LONG_DISPLACEMENT will be set to true if the offset is wider than 7 bits.
907 static bool
908 lex_15_bit_offset (bool *long_displacement, expressionS *exp)
910 char *ilp = input_line_pointer;
912 long val;
913 if (lex_offset (&val))
915 exp->X_op = O_absent;
916 exp->X_add_number = val;
918 else if (lex_expression (exp))
920 if (exp->X_op == O_constant)
922 val = exp->X_add_number;
924 else
926 /* If a symbol was parsed we don't know the displacement.
927 We have to assume it is long, and relax it later if possible. */
928 *long_displacement = true;
929 return true;
932 else
934 exp->X_op = O_absent;
935 goto fail;
938 if (val > 0x3FFF || val < -0x4000)
940 as_fatal (_("Offset is outside of 15 bit range"));
941 return false;
944 *long_displacement = (val > 63 || val < -64);
946 return true;
948 fail:
949 fail_line_pointer = input_line_pointer;
950 input_line_pointer = ilp;
951 return false;
954 static void
955 emit_15_bit_offset (char *f, int where, expressionS *exp)
957 gas_assert (exp);
958 if (exp->X_op != O_absent && exp->X_op != O_constant)
960 exp->X_add_number += where;
961 fixS *fix = fix_new_exp (frag_now,
962 f - frag_now->fr_literal,
964 exp,
965 true,
966 BFD_RELOC_16_PCREL);
967 fix->fx_addnumber = where - 2;
969 else
971 long val = exp->X_add_number;
972 bool long_displacement = (val > 63 || val < -64);
973 if (long_displacement)
974 val |= 0x8000;
975 else
976 val &= 0x7F;
978 number_to_chars_bigendian (f++, val, long_displacement ? 2 : 1);
982 static bool
983 rel (const struct instruction *insn)
985 bool long_displacement;
987 expressionS exp;
988 if (! lex_15_bit_offset (&long_displacement, &exp))
989 return false;
991 char *f = s12z_new_insn (long_displacement ? 3 : 2);
992 number_to_chars_bigendian (f++, insn->opc, 1);
993 emit_15_bit_offset (f, 3, &exp);
994 return true;
997 static bool
998 reg_inh (const struct instruction *insn)
1000 int reg;
1001 if (lex_reg_name (REG_BIT_Dn, &reg))
1003 char *f = s12z_new_insn (insn->page);
1004 if (insn->page == 2)
1005 number_to_chars_bigendian (f++, PAGE2_PREBYTE, 1);
1007 number_to_chars_bigendian (f++, insn->opc + reg, 1);
1008 return true;
1011 return false;
1015 /* Special case for CLR X and CLR Y */
1016 static bool
1017 clr_xy (const struct instruction *insn ATTRIBUTE_UNUSED)
1019 int reg;
1020 if (lex_reg_name (REG_BIT_XY, &reg))
1022 char *f = s12z_new_insn (1);
1023 number_to_chars_bigendian (f, 0x9a + reg - REG_X, 1);
1024 return true;
1027 return false;
1030 /* Some instructions have a suffix like ".l", ".b", ".w" etc
1031 which indicates the size of the operands. */
1032 static int
1033 size_from_suffix (const struct instruction *insn, int idx)
1035 const char *dot = strchr (insn->name, '.');
1037 if (dot == NULL)
1038 return -3;
1040 int size = -2;
1041 switch (dot[1 + idx])
1043 case 'b':
1044 size = 1;
1045 break;
1046 case 'w':
1047 size = 2;
1048 break;
1049 case 'p':
1050 size = 3;
1051 break;
1052 case 'l':
1053 size = 4;
1054 break;
1055 default:
1056 as_fatal (_("Bad size"));
1059 return size;
1062 static bool
1063 mul_reg_reg_reg (const struct instruction *insn)
1065 char *ilp = input_line_pointer;
1067 int Dd;
1068 if (!lex_reg_name (REG_BIT_Dn, &Dd))
1069 goto fail;
1071 if (!lex_match (','))
1072 goto fail;
1074 int Dj;
1075 if (!lex_reg_name (REG_BIT_Dn, &Dj))
1076 goto fail;
1078 if (!lex_match (','))
1079 goto fail;
1081 int Dk;
1082 if (!lex_reg_name (REG_BIT_Dn, &Dk))
1083 goto fail;
1085 char *f = s12z_new_insn (insn->page + 1);
1086 if (insn->page == 2)
1087 number_to_chars_bigendian (f++, PAGE2_PREBYTE, 1);
1089 number_to_chars_bigendian (f++, insn->opc + Dd, 1);
1090 const char *dot = strchrnul (insn->name, '.');
1091 uint8_t mb ;
1092 switch (dot[-1])
1094 case 's':
1095 mb = 0x80;
1096 break;
1097 case 'u':
1098 mb = 0x00;
1099 break;
1100 default:
1101 as_fatal (_("BAD MUL"));
1102 break;
1105 mb |= Dj << 3;
1106 mb |= Dk;
1108 number_to_chars_bigendian (f++, mb, 1);
1110 return true;
1112 fail:
1113 fail_line_pointer = input_line_pointer;
1114 input_line_pointer = ilp;
1115 return false;
1119 static bool
1120 mul_reg_reg_imm (const struct instruction *insn)
1122 char *ilp = input_line_pointer;
1124 int Dd;
1125 if (!lex_reg_name (REG_BIT_Dn, &Dd))
1126 goto fail;
1128 if (!lex_match (','))
1129 goto fail;
1131 int Dj;
1132 if (!lex_reg_name (REG_BIT_Dn, &Dj))
1133 goto fail;
1135 if (!lex_match (','))
1136 goto fail;
1138 long imm;
1139 if (!lex_imm (&imm, NULL))
1140 goto fail;
1143 int size = size_from_suffix (insn, 0);
1145 char *f = s12z_new_insn (insn->page + 1 + size);
1146 if (insn->page == 2)
1147 number_to_chars_bigendian (f++, PAGE2_PREBYTE, 1);
1149 number_to_chars_bigendian (f++, insn->opc + Dd, 1);
1150 uint8_t mb = 0x44;
1151 const char *dot = strchrnul (insn->name, '.');
1152 switch (dot[-1])
1154 case 's':
1155 mb |= 0x80;
1156 break;
1157 case 'u':
1158 mb |= 0x00;
1159 break;
1160 default:
1161 as_fatal (_("BAD MUL"));
1162 break;
1165 mb |= Dj << 3;
1166 mb |= size - 1;
1168 number_to_chars_bigendian (f++, mb, 1);
1169 number_to_chars_bigendian (f++, imm, size);
1171 return true;
1173 fail:
1174 fail_line_pointer = input_line_pointer;
1175 input_line_pointer = ilp;
1176 return false;
1180 static bool
1181 mul_reg_reg_opr (const struct instruction *insn)
1183 char *ilp = input_line_pointer;
1185 int Dd;
1186 if (!lex_reg_name (REG_BIT_Dn, &Dd))
1187 goto fail;
1189 if (!lex_match (','))
1190 goto fail;
1192 int Dj;
1193 if (!lex_reg_name (REG_BIT_Dn, &Dj))
1194 goto fail;
1196 if (!lex_match (','))
1197 goto fail;
1199 uint8_t buffer[4];
1200 int n_bytes;
1201 expressionS exp;
1202 if (!lex_opr (buffer, &n_bytes, &exp, true))
1203 goto fail;
1205 int size = size_from_suffix (insn, 0);
1207 char *f = s12z_new_insn (insn->page + 1 + n_bytes);
1208 if (insn->page == 2)
1209 number_to_chars_bigendian (f++, PAGE2_PREBYTE, 1);
1211 number_to_chars_bigendian (f++, insn->opc + Dd, 1);
1212 uint8_t mb = 0x40;
1213 const char *dot = strchrnul (insn->name, '.');
1214 switch (dot[-1])
1216 case 's':
1217 mb |= 0x80;
1218 break;
1219 case 'u':
1220 mb |= 0x00;
1221 break;
1222 default:
1223 as_fatal (_("BAD MUL"));
1224 break;
1227 mb |= Dj << 3;
1228 mb |= size - 1;
1230 number_to_chars_bigendian (f++, mb, 1);
1232 emit_opr (f, buffer, n_bytes, &exp);
1234 return true;
1236 fail:
1237 fail_line_pointer = input_line_pointer;
1238 input_line_pointer = ilp;
1239 return false;
1242 static bool
1243 mul_reg_opr_opr (const struct instruction *insn)
1245 char *ilp = input_line_pointer;
1247 int Dd;
1248 if (!lex_reg_name (REG_BIT_Dn, &Dd))
1249 goto fail;
1251 if (!lex_match (','))
1252 goto fail;
1254 uint8_t buffer1[4];
1255 int n_bytes1;
1256 expressionS exp1;
1257 if (!lex_opr (buffer1, &n_bytes1, &exp1, false))
1258 goto fail;
1260 if (!lex_match (','))
1261 goto fail;
1263 uint8_t buffer2[4];
1264 int n_bytes2;
1265 expressionS exp2;
1266 if (!lex_opr (buffer2, &n_bytes2, &exp2, false))
1267 goto fail;
1269 int size1 = size_from_suffix (insn, 0);
1270 int size2 = size_from_suffix (insn, 1);
1272 char *f = s12z_new_insn (insn->page + 1 + n_bytes1 + n_bytes2);
1273 if (insn->page == 2)
1274 number_to_chars_bigendian (f++, PAGE2_PREBYTE, 1);
1276 number_to_chars_bigendian (f++, insn->opc + Dd, 1);
1277 uint8_t mb = 0x42;
1278 const char *dot = strchrnul (insn->name, '.');
1279 switch (dot[-1])
1281 case 's':
1282 mb |= 0x80;
1283 break;
1284 case 'u':
1285 mb |= 0x00;
1286 break;
1287 default:
1288 as_fatal (_("BAD MUL"));
1289 break;
1292 mb |= (size1 - 1) << 4;
1293 mb |= (size2 - 1) << 2;
1294 number_to_chars_bigendian (f++, mb, 1);
1296 f = emit_opr (f, buffer1, n_bytes1, &exp1);
1297 f = emit_opr (f, buffer2, n_bytes2, &exp2);
1299 return true;
1301 fail:
1302 fail_line_pointer = input_line_pointer;
1303 input_line_pointer = ilp;
1304 return false;
1308 #define REG_BIT_GRP0 \
1309 ((0x1U << REG_D2) | \
1310 (0x1U << REG_D3) | \
1311 (0x1U << REG_CCH) | \
1312 (0x1U << REG_CCL) | \
1313 (0x1U << REG_D0) | \
1314 (0x1U << REG_D1))
1316 #define REG_BIT_GRP1 \
1317 ((0x1U << REG_D4) | \
1318 (0x1U << REG_D5) | \
1319 (0x1U << REG_D6) | \
1320 (0x1U << REG_D7) | \
1321 (0x1U << REG_X) | \
1322 (0x1U << REG_Y))
1324 static const uint8_t reg_map [] =
1326 0x02, /* D2 */
1327 0x01, /* D3 */
1328 0x20,
1329 0x10, /* D5 */
1330 0x08, /* D0 */
1331 0x04, /* D1 */
1332 0x08, /* D6 */
1333 0x04, /* D7 */
1334 0x02,
1335 0x01, /* Y */
1336 0x00,
1337 0x00,
1338 0x20, /* CCH */
1339 0x10, /* CCL */
1340 0x00
1343 static bool
1344 lex_reg_list (uint16_t grp, uint16_t *reg_bits)
1346 if (lex_match (','))
1348 int reg;
1349 if (!lex_reg_name (grp, &reg))
1350 return false;
1351 *reg_bits |= 0x1u << reg;
1352 lex_reg_list (grp, reg_bits);
1355 /* Empty list */
1356 return true;
1359 static bool
1360 psh_pull (const struct instruction *insn)
1362 uint8_t pb =
1363 (0 == strcmp ("pul", insn->name)) ? 0x80: 0x00;
1365 if (lex_match_string ("all16b"))
1367 pb |= 0x40;
1369 else if (lex_match_string ("all"))
1371 /* Nothing to do */
1373 else
1375 int reg1;
1376 if (!lex_reg_name (REG_BIT_GRP1 | REG_BIT_GRP0, &reg1))
1377 goto fail;
1378 uint16_t admitted_group = 0;
1380 if ((0x1U << reg1) & REG_BIT_GRP1)
1381 admitted_group = REG_BIT_GRP1;
1382 else if ((0x1U << reg1) & REG_BIT_GRP0)
1383 admitted_group = REG_BIT_GRP0;
1385 uint16_t reg_bits = 0x1 << reg1;
1386 if (!lex_reg_list (admitted_group, &reg_bits))
1387 goto fail;
1389 if (reg_bits & REG_BIT_GRP1)
1390 pb |= 0x40;
1392 int i;
1393 for (i = 0; i < 16; ++i)
1395 if (reg_bits & (0x1u << i))
1396 pb |= reg_map[i];
1400 char *f = s12z_new_insn (2);
1401 number_to_chars_bigendian (f++, insn->opc, 1);
1402 number_to_chars_bigendian (f++, pb, 1);
1403 return true;
1405 fail:
1406 fail_line_pointer = input_line_pointer;
1407 return false;
1411 static bool
1412 tfr (const struct instruction *insn)
1414 int reg1;
1415 if (!lex_reg_name (~0, &reg1))
1416 goto fail;
1418 if (!lex_match (','))
1419 goto fail;
1421 int reg2;
1422 if (!lex_reg_name (~0, &reg2))
1423 goto fail;
1425 if ( ((0 == strcasecmp ("sex", insn->name))
1426 || (0 == strcasecmp ("zex", insn->name)))
1427 && (registers[reg2].bytes <= registers[reg1].bytes))
1428 as_warn (_("Source register for %s is no larger than the destination register"),
1429 insn->name);
1430 else if (reg1 == reg2)
1431 as_warn (_("The destination and source registers are identical"));
1433 char *f = s12z_new_insn (1 + insn->page);
1434 if (insn->page == 2)
1435 number_to_chars_bigendian (f++, PAGE2_PREBYTE, 1);
1437 number_to_chars_bigendian (f++, insn->opc, 1);
1438 number_to_chars_bigendian (f++, reg1 << 4 | reg2, 1);
1440 return true;
1442 fail:
1443 fail_line_pointer = input_line_pointer;
1444 return false;
1447 static bool
1448 imm8 (const struct instruction *insn)
1450 long imm;
1451 if (! lex_imm (&imm, NULL))
1452 return false;
1453 if (imm > 127 || imm < -128)
1455 as_bad (_("Immediate value %ld is out of range for instruction %s"),
1456 imm, insn->name);
1459 char *f = s12z_new_insn (2);
1460 number_to_chars_bigendian (f++, insn->opc, 1);
1461 number_to_chars_bigendian (f++, imm, 1);
1463 return true;
1466 static bool
1467 reg_imm (const struct instruction *insn, int allowed_reg)
1469 char *ilp = input_line_pointer;
1470 int reg;
1471 if (lex_reg_name (allowed_reg, &reg))
1473 if (!lex_force_match (','))
1474 goto fail;
1475 long imm;
1476 if (! lex_imm (&imm, NULL))
1477 goto fail;
1479 short size = registers[reg].bytes;
1480 char *f = s12z_new_insn (insn->page + size);
1481 if (insn->page == 2)
1482 number_to_chars_bigendian (f++, PAGE2_PREBYTE, 1);
1484 number_to_chars_bigendian (f++, insn->opc + reg, 1);
1485 number_to_chars_bigendian (f++, imm, size);
1486 return true;
1489 fail:
1490 fail_line_pointer = input_line_pointer;
1491 input_line_pointer = ilp;
1492 return false;
1496 static bool
1497 regd_imm (const struct instruction *insn)
1499 return reg_imm (insn, REG_BIT_Dn);
1502 static bool
1503 regdxy_imm (const struct instruction *insn)
1505 return reg_imm (insn, REG_BIT_Dn | REG_BIT_XY);
1509 static bool
1510 regs_imm (const struct instruction *insn)
1512 return reg_imm (insn, 0x1U << REG_S);
1515 static bool
1516 trap_imm (const struct instruction *insn ATTRIBUTE_UNUSED)
1518 long imm = -1;
1519 if (! lex_imm (&imm, NULL))
1520 goto fail;
1522 if (imm < 0x92 || imm > 0xFF ||
1523 (imm >= 0xA0 && imm <= 0xA7) ||
1524 (imm >= 0xB0 && imm <= 0xB7))
1526 as_bad (_("trap value %ld is not valid"), imm);
1527 return false;
1529 else
1531 char *f = s12z_new_insn (2);
1532 number_to_chars_bigendian (f++, PAGE2_PREBYTE, 1);
1533 number_to_chars_bigendian (f++, imm & 0xFF, 1);
1534 return true;
1537 return true;
1539 fail:
1540 fail_line_pointer = input_line_pointer;
1541 return false;
1546 /* Special one byte instruction CMP X, Y */
1547 static bool
1548 regx_regy (const struct instruction *insn)
1550 int reg;
1551 if (lex_reg_name (0x1U << REG_X, &reg))
1553 if (lex_force_match (','))
1555 if (lex_reg_name (0x1U << REG_Y, &reg))
1557 char *f = s12z_new_insn (1);
1558 number_to_chars_bigendian (f, insn->opc, 1);
1559 return true;
1563 return false;
1566 /* Special one byte instruction SUB D6, X, Y */
1567 static bool
1568 regd6_regx_regy (const struct instruction *insn)
1570 char *ilp = input_line_pointer;
1571 int reg;
1572 if (!lex_reg_name (0x1U << REG_D6, &reg))
1573 goto fail;
1575 if (!lex_match (','))
1576 goto fail;
1578 if (!lex_reg_name (0x1U << REG_X, &reg))
1579 goto fail;
1581 if (!lex_match (','))
1582 goto fail;
1584 if (!lex_reg_name (0x1U << REG_Y, &reg))
1585 goto fail;
1587 char *f = s12z_new_insn (1);
1588 number_to_chars_bigendian (f, insn->opc, 1);
1589 return true;
1591 fail:
1592 fail_line_pointer = input_line_pointer;
1593 input_line_pointer = ilp;
1594 return false;
1597 /* Special one byte instruction SUB D6, Y, X */
1598 static bool
1599 regd6_regy_regx (const struct instruction *insn)
1601 char *ilp = input_line_pointer;
1602 int reg;
1603 if (!lex_reg_name (0x1U << REG_D6, &reg))
1604 goto fail;
1606 if (!lex_match (','))
1607 goto fail;
1609 if (!lex_reg_name (0x1U << REG_Y, &reg))
1610 goto fail;
1612 if (!lex_match (','))
1613 goto fail;
1615 if (!lex_reg_name (0x1U << REG_X, &reg))
1616 goto fail;
1618 char *f = s12z_new_insn (1);
1619 number_to_chars_bigendian (f, insn->opc, 1);
1620 return true;
1622 fail:
1623 fail_line_pointer = input_line_pointer;
1624 input_line_pointer = ilp;
1625 return false;
1628 static bool
1629 reg_opr (const struct instruction *insn, int allowed_regs,
1630 bool immediate_ok)
1632 char *ilp = input_line_pointer;
1633 int reg;
1634 if (lex_reg_name (allowed_regs, &reg))
1636 if (!lex_force_match (','))
1637 goto fail;
1639 uint8_t buffer[4];
1640 int n_bytes;
1641 expressionS exp;
1642 if (lex_opr (buffer, &n_bytes, &exp, immediate_ok))
1644 /* Large constant direct values are more efficiently encoded as ext24 mode.
1645 Otherwise a decision has to be deferred to a relax. */
1646 if (exp.X_op == O_constant
1647 && buffer[0] == 0xFA
1648 && insn->alt_opc != 0)
1650 char *f = s12z_new_insn (4);
1652 /* I don't think there are any instances of page 2 opcodes in this case */
1653 gas_assert (insn->page == 1);
1655 number_to_chars_bigendian (f++, insn->alt_opc + reg, 1);
1657 emit_ext24 (f, exp.X_add_number);
1659 else
1661 char *f = s12z_new_insn (n_bytes + insn->page);
1663 if (insn->page == 2)
1664 number_to_chars_bigendian (f++, PAGE2_PREBYTE, 1);
1666 number_to_chars_bigendian (f++, insn->opc + reg, 1);
1668 emit_opr (f, buffer, n_bytes, &exp);
1671 return true;
1675 fail:
1676 fail_line_pointer = input_line_pointer;
1677 input_line_pointer = ilp;
1678 return false;
1682 static bool
1683 regdxy_opr_dest (const struct instruction *insn)
1685 return reg_opr (insn, REG_BIT_Dn | REG_BIT_XY, false);
1688 static bool
1689 regdxy_opr_src (const struct instruction *insn)
1691 return reg_opr (insn, REG_BIT_Dn | REG_BIT_XY, true);
1695 static bool
1696 regd_opr (const struct instruction *insn)
1698 return reg_opr (insn, REG_BIT_Dn, true);
1702 /* OP0: S; OP1: destination OPR */
1703 static bool
1704 regs_opr_dest (const struct instruction *insn)
1706 return reg_opr (insn, 0x1U << REG_S, false);
1709 /* OP0: S; OP1: source OPR */
1710 static bool
1711 regs_opr_src (const struct instruction *insn)
1713 return reg_opr (insn, 0x1U << REG_S, true);
1716 static bool
1717 imm_opr (const struct instruction *insn)
1719 char *ilp = input_line_pointer;
1720 long imm;
1721 expressionS exp0;
1722 int size = size_from_suffix (insn, 0);
1723 exp0.X_op = O_absent;
1725 /* Note: The ternary expression below means that "MOV.x #symbol,
1726 mem-expr" is accepted when x is a member of {'w', 'p', 'l'} but
1727 not when it is 'b'.
1728 The Freescale assembler accepts "MOV.b #symbol, mem-expr" but
1729 produces obviously incorrect code. Since such an instruction
1730 would require an 8-bit reloc (which we don't have) and some
1731 non-optimal kludges in the OPR encoding, it seems sensible that
1732 such instructions should be rejected. */
1733 if (!lex_imm (&imm, size > 1 ? &exp0 : NULL))
1734 goto fail;
1736 if (!lex_match (','))
1737 goto fail;
1739 uint8_t buffer[4];
1740 int n_bytes;
1741 expressionS exp1;
1742 if (!lex_opr (buffer, &n_bytes, &exp1, false))
1743 goto fail;
1745 char *f = s12z_new_insn (1 + n_bytes + size);
1746 number_to_chars_bigendian (f++, insn->opc, 1);
1748 emit_reloc (&exp0, f, size, size == 4 ? BFD_RELOC_32 : BFD_RELOC_S12Z_OPR);
1750 int i;
1751 for (i = 0; i < size; ++i)
1752 number_to_chars_bigendian (f++, imm >> (CHAR_BIT * (size - i - 1)), 1);
1754 emit_opr (f, buffer, n_bytes, &exp1);
1756 return true;
1758 fail:
1759 fail_line_pointer = input_line_pointer;
1760 input_line_pointer = ilp;
1761 return false;
1764 static bool
1765 opr_opr (const struct instruction *insn)
1767 char *ilp = input_line_pointer;
1769 uint8_t buffer1[4];
1770 int n_bytes1;
1771 expressionS exp1;
1772 if (!lex_opr (buffer1, &n_bytes1, &exp1, false))
1773 goto fail;
1776 if (!lex_match (','))
1777 goto fail;
1779 uint8_t buffer2[4];
1780 int n_bytes2;
1781 expressionS exp2;
1782 if (!lex_opr (buffer2, &n_bytes2, &exp2, false))
1783 goto fail;
1785 char *f = s12z_new_insn (1 + n_bytes1 + n_bytes2);
1786 number_to_chars_bigendian (f++, insn->opc, 1);
1788 f = emit_opr (f, buffer1, n_bytes1, &exp1);
1789 f = emit_opr (f, buffer2, n_bytes2, &exp2);
1791 return true;
1793 fail:
1794 fail_line_pointer = input_line_pointer;
1795 input_line_pointer = ilp;
1796 return false;
1799 static bool
1800 reg67sxy_opr (const struct instruction *insn)
1802 int reg;
1803 if (!lex_reg_name (REG_BIT_XYS | (0x1U << REG_D6) | (0x1U << REG_D7), &reg))
1804 return false;
1806 if (!lex_match (','))
1807 return false;
1809 uint8_t buffer[4];
1810 int n_bytes;
1811 expressionS exp;
1812 if (!lex_opr (buffer, &n_bytes, &exp, false))
1813 return false;
1815 char *f = s12z_new_insn (1 + n_bytes);
1816 number_to_chars_bigendian (f++, insn->opc + reg - REG_D6, 1);
1817 emit_opr (f, buffer, n_bytes, &exp);
1819 return true;
1822 static bool
1823 rotate (const struct instruction *insn, short dir)
1825 uint8_t buffer[4];
1826 int n_bytes;
1827 expressionS exp;
1828 if (lex_opr (buffer, &n_bytes, &exp, false))
1830 char *f = s12z_new_insn (n_bytes + 2);
1831 number_to_chars_bigendian (f++, insn->opc, 1);
1832 int size = size_from_suffix (insn, 0);
1833 if (size < 0)
1834 size = 1;
1835 uint8_t sb = 0x24;
1836 sb |= size - 1;
1837 if (dir)
1838 sb |= 0x40;
1839 number_to_chars_bigendian (f++, sb, 1);
1840 emit_opr (f, buffer, n_bytes, &exp);
1842 return true;
1845 return false;
1848 static bool
1849 rol (const struct instruction *insn)
1851 return rotate (insn, 1);
1854 static bool
1855 ror (const struct instruction *insn)
1857 return rotate (insn, 0);
1861 /* Shift instruction with a register operand and an immediate #1 or #2
1862 left = 1; right = 0;
1863 logical = 0; arithmetic = 1;
1865 static bool
1866 lex_shift_reg_imm1 (const struct instruction *insn, short type, short dir)
1869 This function is highly unusual and a bit wierd!
1870 It first matches the input against a register {d0, d1, ... d7} followed by an immediate
1871 {#1, #2}.
1872 Then, it rewinds the input and parses it again as a OPR.
1874 char *ilp = input_line_pointer;
1876 int Dd;
1877 if (!lex_reg_name (REG_BIT_Dn, &Dd))
1879 goto fail;
1882 if (!lex_match (','))
1883 goto fail;
1885 long imm = -1;
1886 if (!lex_imm (&imm, NULL))
1887 goto fail;
1889 if (imm != 1 && imm != 2)
1890 goto fail;
1891 input_line_pointer = ilp;
1893 /* Now parse the first operand again */
1895 uint8_t buffer[4];
1896 int n_bytes;
1898 expressionS exp;
1899 if (!lex_opr (buffer, &n_bytes, &exp, false))
1900 goto fail;
1902 gas_assert (n_bytes == 1);
1904 uint8_t sb = 0x34;
1905 sb |= dir << 6;
1906 sb |= type << 7;
1907 if (imm == 2)
1908 sb |= 0x08;
1910 char *f = s12z_new_insn (3);
1911 number_to_chars_bigendian (f++, insn->opc, 1);
1912 number_to_chars_bigendian (f++, sb, 1);
1913 emit_opr (f, buffer, n_bytes, &exp);
1915 return true;
1917 fail:
1918 fail_line_pointer = input_line_pointer;
1919 input_line_pointer = ilp;
1920 return false;
1923 /* Shift instruction with a register operand.
1924 left = 1; right = 0;
1925 logical = 0; arithmetic = 1; */
1926 static bool
1927 lex_shift_reg (const struct instruction *insn, short type, short dir)
1929 int Dd, Ds, Dn;
1930 if (!lex_reg_name (REG_BIT_Dn, &Dd))
1932 goto fail;
1935 if (!lex_match (','))
1936 goto fail;
1938 if (!lex_reg_name (REG_BIT_Dn, &Ds))
1940 goto fail;
1943 if (!lex_match (','))
1944 goto fail;
1946 uint8_t sb = 0x10;
1947 sb |= Ds;
1948 sb |= dir << 6;
1949 sb |= type << 7;
1950 long imm;
1951 if (lex_reg_name (REG_BIT_Dn, &Dn))
1953 char *f = s12z_new_insn (3);
1954 number_to_chars_bigendian (f++, insn->opc | Dd, 1);
1955 number_to_chars_bigendian (f++, sb, 1);
1956 uint8_t xb = 0xb8;
1957 xb |= Dn;
1958 number_to_chars_bigendian (f++, xb, 1);
1960 return true;
1962 else if (lex_imm (&imm, NULL))
1964 if (imm < 0 || imm > 31)
1966 as_bad (_("Shift value should be in the range [0,31]"));
1967 goto fail;
1970 int n_bytes = 3;
1971 if (imm == 1 || imm == 2)
1973 n_bytes = 2;
1974 sb &= ~0x10;
1976 else
1978 sb |= (imm & 0x01) << 3;
1981 char *f = s12z_new_insn (n_bytes);
1982 number_to_chars_bigendian (f++, insn->opc | Dd, 1);
1983 number_to_chars_bigendian (f++, sb, 1);
1984 if (n_bytes > 2)
1986 uint8_t xb = 0x70;
1987 xb |= imm >> 1;
1988 number_to_chars_bigendian (f++, xb, 1);
1991 return true;
1994 fail:
1995 fail_line_pointer = input_line_pointer;
1996 return false;
1999 static void
2000 impute_shift_dir_and_type (const struct instruction *insn, short *type, short *dir)
2002 *dir = -1;
2003 *type = -1;
2004 switch (insn->name[0])
2006 case 'l':
2007 *type = 0;
2008 break;
2009 case 'a':
2010 *type = 1;
2011 break;
2012 default:
2013 as_fatal (_("Bad shift mode"));
2014 break;
2017 switch (insn->name[2])
2019 case 'l':
2020 *dir = 1;
2021 break;
2022 case 'r':
2023 *dir = 0;
2024 break;
2025 default:
2026 as_fatal (_("Bad shift *direction"));
2027 break;
2031 /* Shift instruction with a OPR operand */
2032 static bool
2033 shift_two_operand (const struct instruction *insn)
2035 uint8_t sb = 0x34;
2036 char *ilp = input_line_pointer;
2038 short dir = -1;
2039 short type = -1;
2040 impute_shift_dir_and_type (insn, &type, &dir);
2041 sb |= dir << 6;
2042 sb |= type << 7;
2044 int size = size_from_suffix (insn, 0);
2045 sb |= size - 1;
2047 uint8_t buffer[4];
2048 int n_opr_bytes;
2049 expressionS exp;
2050 if (!lex_opr (buffer, &n_opr_bytes, &exp, false))
2051 goto fail;
2053 if (!lex_match (','))
2054 goto fail;
2056 long imm = -1;
2057 if (!lex_imm (&imm, NULL))
2058 goto fail;
2060 if (imm != 1 && imm != 2)
2061 goto fail;
2063 if (imm == 2)
2064 sb |= 0x08;
2066 char *f = s12z_new_insn (2 + n_opr_bytes);
2067 number_to_chars_bigendian (f++, insn->opc, 1);
2068 number_to_chars_bigendian (f++, sb, 1);
2069 emit_opr (f, buffer, n_opr_bytes, &exp);
2071 return true;
2073 fail:
2074 fail_line_pointer = input_line_pointer;
2075 input_line_pointer = ilp;
2076 return false;
2079 /* Shift instruction with a OPR operand */
2080 static bool
2081 shift_opr_imm (const struct instruction *insn)
2083 char *ilp = input_line_pointer;
2085 short dir = -1;
2086 short type = -1;
2087 impute_shift_dir_and_type (insn, &type, &dir);
2089 int Dd = 0;
2090 if (!lex_reg_name (REG_BIT_Dn, &Dd))
2091 goto fail;
2093 if (!lex_match (','))
2094 goto fail;
2096 int n_bytes = 2;
2098 uint8_t buffer1[4];
2099 int n_opr_bytes1;
2101 expressionS exp1;
2102 if (!lex_opr (buffer1, &n_opr_bytes1, &exp1, false))
2103 goto fail;
2105 n_bytes += n_opr_bytes1;
2106 if (!lex_match (','))
2107 goto fail;
2109 uint8_t buffer2[4];
2110 int n_opr_bytes2 = 0;
2111 expressionS exp2;
2112 long imm;
2113 bool immediate = false;
2114 if (lex_imm (&imm, NULL))
2116 immediate = true;
2118 else if (!lex_opr (buffer2, &n_opr_bytes2, &exp2, false))
2119 goto fail;
2121 uint8_t sb = 0x20;
2123 int size = size_from_suffix (insn, 0);
2125 if (size != -1)
2126 sb |= size - 1;
2128 sb |= dir << 6;
2129 sb |= type << 7;
2131 if (immediate)
2133 if (imm == 2 || imm == 1)
2135 if (imm == 2)
2136 sb |= 0x08;
2138 else
2140 n_bytes++;
2141 sb |= 0x10;
2142 if (imm % 2)
2143 sb |= 0x08;
2146 else
2148 n_bytes += n_opr_bytes2;
2149 sb |= 0x10;
2152 char *f = s12z_new_insn (n_bytes);
2153 number_to_chars_bigendian (f++, insn->opc | Dd, 1);
2154 number_to_chars_bigendian (f++, sb, 1);
2155 f = emit_opr (f, buffer1, n_opr_bytes1, &exp1);
2156 if (immediate)
2158 if (imm != 1 && imm != 2)
2160 number_to_chars_bigendian (f++, 0x70 | (imm >> 1), 1);
2163 else
2165 f = emit_opr (f, buffer2, n_opr_bytes2, &exp2);
2168 return true;
2170 fail:
2171 fail_line_pointer = input_line_pointer;
2172 input_line_pointer = ilp;
2173 return false;
2176 /* Shift instruction with a register operand */
2177 static bool
2178 shift_reg (const struct instruction *insn)
2180 short dir = -1;
2181 short type = -1;
2182 impute_shift_dir_and_type (insn, &type, &dir);
2184 if (lex_shift_reg_imm1 (insn, type, dir))
2185 return true;
2187 return lex_shift_reg (insn, type, dir);
2190 static bool
2191 bm_regd_imm (const struct instruction *insn)
2193 char *ilp = input_line_pointer;
2194 int Di = 0;
2195 if (!lex_reg_name (REG_BIT_Dn, &Di))
2196 goto fail;
2198 if (!lex_match (','))
2199 goto fail;
2201 long imm;
2202 if (!lex_imm (&imm, NULL))
2203 goto fail;
2206 uint8_t bm = imm << 3;
2207 bm |= Di;
2209 char *f = s12z_new_insn (2);
2210 number_to_chars_bigendian (f++, insn->opc, 1);
2211 number_to_chars_bigendian (f++, bm, 1);
2213 return true;
2215 fail:
2216 fail_line_pointer = input_line_pointer;
2217 input_line_pointer = ilp;
2218 return false;
2221 static bool
2222 bm_opr_reg (const struct instruction *insn)
2224 char *ilp = input_line_pointer;
2226 uint8_t buffer[4];
2227 int n_opr_bytes;
2229 expressionS exp;
2230 if (!lex_opr (buffer, &n_opr_bytes, &exp, false))
2231 goto fail;
2233 if (!lex_match (','))
2234 goto fail;
2236 int Dn = 0;
2237 if (!lex_reg_name (REG_BIT_Dn, &Dn))
2238 goto fail;
2240 uint8_t bm = Dn << 4;
2241 int size = size_from_suffix (insn, 0);
2242 bm |= (size - 1) << 2;
2243 bm |= 0x81;
2245 char *f = s12z_new_insn (2 + n_opr_bytes);
2246 number_to_chars_bigendian (f++, insn->opc, 1);
2247 number_to_chars_bigendian (f++, bm, 1);
2249 emit_opr (f, buffer, n_opr_bytes, &exp);
2251 return true;
2253 fail:
2254 fail_line_pointer = input_line_pointer;
2255 input_line_pointer = ilp;
2256 return false;
2260 static bool
2261 bm_opr_imm (const struct instruction *insn)
2263 char *ilp = input_line_pointer;
2265 uint8_t buffer[4];
2266 int n_opr_bytes;
2268 expressionS exp;
2269 if (!lex_opr (buffer, &n_opr_bytes, &exp, false))
2270 goto fail;
2272 if (!lex_match (','))
2273 goto fail;
2276 long imm;
2277 if (!lex_imm (&imm, NULL))
2278 goto fail;
2280 int size = size_from_suffix (insn, 0);
2282 if (imm < 0 || imm >= size * 8)
2284 as_bad (_("Immediate operand %ld is inappropriate for size of instruction"), imm);
2285 goto fail;
2288 uint8_t bm = 0x80;
2289 if (size == 2)
2290 bm |= 0x02;
2291 else if (size == 4)
2292 bm |= 0x08;
2293 bm |= (imm & 0x07) << 4;
2294 bm |= (imm >> 3);
2297 char *f = s12z_new_insn (2 + n_opr_bytes);
2298 number_to_chars_bigendian (f++, insn->opc, 1);
2299 number_to_chars_bigendian (f++, bm, 1);
2300 emit_opr (f, buffer, n_opr_bytes, &exp);
2302 return true;
2304 fail:
2305 fail_line_pointer = input_line_pointer;
2306 input_line_pointer = ilp;
2307 return false;
2311 static bool
2312 bm_regd_reg (const struct instruction *insn)
2314 char *ilp = input_line_pointer;
2315 int Di = 0;
2316 if (!lex_reg_name (REG_BIT_Dn, &Di))
2317 goto fail;
2319 if (!lex_match (','))
2320 goto fail;
2322 int Dn = 0;
2323 if (!lex_reg_name (REG_BIT_Dn, &Dn))
2324 goto fail;
2326 uint8_t bm = Dn << 4;
2327 bm |= 0x81;
2329 uint8_t xb = Di | 0xb8;
2331 char *f = s12z_new_insn (3);
2332 number_to_chars_bigendian (f++, insn->opc, 1);
2333 number_to_chars_bigendian (f++, bm, 1);
2334 number_to_chars_bigendian (f++, xb, 1);
2336 return true;
2338 fail:
2339 fail_line_pointer = input_line_pointer;
2340 input_line_pointer = ilp;
2341 return false;
2348 static bool
2349 bf_reg_opr_imm (const struct instruction *insn, short ie)
2351 char *ilp = input_line_pointer;
2352 int Dd = 0;
2353 if (!lex_reg_name (REG_BIT_Dn, &Dd))
2354 goto fail;
2356 if (!lex_match (','))
2357 goto fail;
2359 uint8_t buffer[4];
2360 int n_bytes;
2362 expressionS exp;
2363 if (!lex_opr (buffer, &n_bytes, &exp, false))
2364 goto fail;
2366 if (!lex_match (','))
2367 goto fail;
2369 long width;
2370 if (!lex_imm (&width, NULL))
2371 goto fail;
2373 if (width < 0 || width > 31)
2375 as_bad (_("Invalid width value for %s"), insn->name);
2376 goto fail;
2379 if (!lex_match (':'))
2380 goto fail;
2382 long offset;
2383 if (!lex_constant (&offset))
2384 goto fail;
2386 if (offset < 0 || offset > 31)
2388 as_bad (_("Invalid offset value for %s"), insn->name);
2389 goto fail;
2392 uint8_t i1 = width << 5;
2393 i1 |= offset;
2395 int size = size_from_suffix (insn, 0);
2396 uint8_t bb = ie ? 0x80 : 0x00;
2397 bb |= 0x60;
2398 bb |= (size - 1) << 2;
2399 bb |= width >> 3;
2401 char *f = s12z_new_insn (4 + n_bytes);
2402 number_to_chars_bigendian (f++, PAGE2_PREBYTE, 1);
2403 number_to_chars_bigendian (f++, 0x08 | Dd, 1);
2404 number_to_chars_bigendian (f++, bb, 1);
2405 number_to_chars_bigendian (f++, i1, 1);
2407 emit_opr (f, buffer, n_bytes, &exp);
2409 return true;
2411 fail:
2412 fail_line_pointer = input_line_pointer;
2413 input_line_pointer = ilp;
2414 return false;
2418 static bool
2419 bf_opr_reg_imm (const struct instruction *insn, short ie)
2421 char *ilp = input_line_pointer;
2422 uint8_t buffer[4];
2423 int n_bytes;
2424 expressionS exp;
2425 if (!lex_opr (buffer, &n_bytes, &exp, false))
2426 goto fail;
2428 if (!lex_match (','))
2429 goto fail;
2431 int Ds = 0;
2432 if (!lex_reg_name (REG_BIT_Dn, &Ds))
2433 goto fail;
2435 if (!lex_match (','))
2436 goto fail;
2438 long width;
2439 if (!lex_imm (&width, NULL))
2440 goto fail;
2442 if (width < 0 || width > 31)
2444 as_bad (_("Invalid width value for %s"), insn->name);
2445 goto fail;
2448 if (!lex_match (':'))
2449 goto fail;
2451 long offset;
2452 if (!lex_constant (&offset))
2453 goto fail;
2455 if (offset < 0 || offset > 31)
2457 as_bad (_("Invalid offset value for %s"), insn->name);
2458 goto fail;
2461 uint8_t i1 = width << 5;
2462 i1 |= offset;
2464 int size = size_from_suffix (insn, 0);
2465 uint8_t bb = ie ? 0x80 : 0x00;
2466 bb |= 0x70;
2467 bb |= (size - 1) << 2;
2468 bb |= width >> 3;
2470 char *f = s12z_new_insn (4 + n_bytes);
2471 number_to_chars_bigendian (f++, PAGE2_PREBYTE, 1);
2472 number_to_chars_bigendian (f++, 0x08 | Ds, 1);
2473 number_to_chars_bigendian (f++, bb, 1);
2474 number_to_chars_bigendian (f++, i1, 1);
2476 emit_opr (f, buffer, n_bytes, &exp);
2478 return true;
2480 fail:
2481 fail_line_pointer = input_line_pointer;
2482 input_line_pointer = ilp;
2483 return false;
2488 static bool
2489 bf_reg_reg_imm (const struct instruction *insn, short ie)
2491 char *ilp = input_line_pointer;
2492 int Dd = 0;
2493 if (!lex_reg_name (REG_BIT_Dn, &Dd))
2494 goto fail;
2496 if (!lex_match (','))
2497 goto fail;
2499 int Ds = 0;
2500 if (!lex_reg_name (REG_BIT_Dn, &Ds))
2501 goto fail;
2503 if (!lex_match (','))
2504 goto fail;
2506 long width;
2507 if (!lex_imm (&width, NULL))
2508 goto fail;
2510 if (width < 0 || width > 31)
2512 as_bad (_("Invalid width value for %s"), insn->name);
2513 goto fail;
2516 if (!lex_match (':'))
2517 goto fail;
2519 long offset;
2520 if (!lex_constant (&offset))
2521 goto fail;
2523 if (offset < 0 || offset > 31)
2525 as_bad (_("Invalid offset value for %s"), insn->name);
2526 goto fail;
2529 uint8_t bb = ie ? 0x80 : 0x00;
2530 bb |= 0x20;
2531 bb |= Ds << 2;
2532 bb |= width >> 3;
2534 uint8_t i1 = width << 5;
2535 i1 |= offset;
2537 char *f = s12z_new_insn (4);
2538 number_to_chars_bigendian (f++, PAGE2_PREBYTE, 1);
2539 number_to_chars_bigendian (f++, 0x08 | Dd, 1);
2540 number_to_chars_bigendian (f++, bb, 1);
2541 number_to_chars_bigendian (f++, i1, 1);
2543 return true;
2545 fail:
2546 fail_line_pointer = input_line_pointer;
2547 input_line_pointer = ilp;
2548 return false;
2551 static bool
2552 bf_reg_reg_reg (const struct instruction *insn ATTRIBUTE_UNUSED, short ie)
2554 char *ilp = input_line_pointer;
2555 int Dd = 0;
2556 if (!lex_reg_name (REG_BIT_Dn, &Dd))
2557 goto fail;
2559 if (!lex_match (','))
2560 goto fail;
2562 int Ds = 0;
2563 if (!lex_reg_name (REG_BIT_Dn, &Ds))
2564 goto fail;
2566 if (!lex_match (','))
2567 goto fail;
2569 int Dp = 0;
2570 if (!lex_reg_name ((0x01u << REG_D2) |
2571 (0x01u << REG_D3) |
2572 (0x01u << REG_D4) |
2573 (0x01u << REG_D5),
2574 &Dp))
2575 goto fail;
2577 uint8_t bb = ie ? 0x80 : 0x00;
2578 bb |= Ds << 2;
2579 bb |= Dp;
2581 char *f = s12z_new_insn (3);
2582 number_to_chars_bigendian (f++, PAGE2_PREBYTE, 1);
2583 number_to_chars_bigendian (f++, 0x08 | Dd, 1);
2584 number_to_chars_bigendian (f++, bb , 1);
2586 return true;
2588 fail:
2589 fail_line_pointer = input_line_pointer;
2590 input_line_pointer = ilp;
2591 return false;
2594 static bool
2595 bf_opr_reg_reg (const struct instruction *insn, short ie)
2597 char *ilp = input_line_pointer;
2599 uint8_t buffer[4];
2600 int n_bytes;
2601 expressionS exp;
2602 if (!lex_opr (buffer, &n_bytes, &exp, false))
2603 goto fail;
2605 if (!lex_match (','))
2606 goto fail;
2609 int Ds = 0;
2610 if (!lex_reg_name (REG_BIT_Dn, &Ds))
2611 goto fail;
2613 if (!lex_match (','))
2614 goto fail;
2617 int Dp = 0;
2618 if (!lex_reg_name ((0x01u << REG_D2) |
2619 (0x01u << REG_D3) |
2620 (0x01u << REG_D4) |
2621 (0x01u << REG_D5),
2622 &Dp))
2623 goto fail;
2625 int size = size_from_suffix (insn, 0);
2626 uint8_t bb = ie ? 0x80 : 0x00;
2627 bb |= 0x50;
2628 bb |= Dp;
2629 bb |= (size - 1) << 2;
2631 char *f = s12z_new_insn (3 + n_bytes);
2632 number_to_chars_bigendian (f++, PAGE2_PREBYTE, 1);
2633 number_to_chars_bigendian (f++, 0x08 | Ds, 1);
2634 number_to_chars_bigendian (f++, bb , 1);
2636 emit_opr (f, buffer, n_bytes, &exp);
2638 return true;
2640 fail:
2641 fail_line_pointer = input_line_pointer;
2642 input_line_pointer = ilp;
2643 return false;
2647 static bool
2648 bf_reg_opr_reg (const struct instruction *insn, short ie)
2650 char *ilp = input_line_pointer;
2651 int Dd = 0;
2652 if (!lex_reg_name (REG_BIT_Dn, &Dd))
2653 goto fail;
2655 if (!lex_match (','))
2656 goto fail;
2659 uint8_t buffer[4];
2660 int n_bytes;
2661 expressionS exp;
2662 if (!lex_opr (buffer, &n_bytes, &exp, false))
2663 goto fail;
2665 if (!lex_match (','))
2666 goto fail;
2668 int Dp = 0;
2669 if (!lex_reg_name ((0x01u << REG_D2) |
2670 (0x01u << REG_D3) |
2671 (0x01u << REG_D4) |
2672 (0x01u << REG_D5),
2673 &Dp))
2674 goto fail;
2676 int size = size_from_suffix (insn, 0);
2677 uint8_t bb = ie ? 0x80 : 0x00;
2678 bb |= 0x40;
2679 bb |= Dp;
2680 bb |= (size - 1) << 2;
2682 char *f = s12z_new_insn (3 + n_bytes);
2683 number_to_chars_bigendian (f++, PAGE2_PREBYTE, 1);
2684 number_to_chars_bigendian (f++, 0x08 | Dd, 1);
2685 number_to_chars_bigendian (f++, bb , 1);
2687 emit_opr (f, buffer, n_bytes, &exp);
2689 return true;
2691 fail:
2692 fail_line_pointer = input_line_pointer;
2693 input_line_pointer = ilp;
2694 return false;
2699 static bool
2700 bfe_reg_reg_reg (const struct instruction *insn)
2702 return bf_reg_reg_reg (insn, 0);
2705 static bool
2706 bfi_reg_reg_reg (const struct instruction *insn)
2708 return bf_reg_reg_reg (insn, 1);
2711 static bool
2712 bfe_reg_reg_imm (const struct instruction *insn)
2714 return bf_reg_reg_imm (insn, 0);
2717 static bool
2718 bfi_reg_reg_imm (const struct instruction *insn)
2720 return bf_reg_reg_imm (insn, 1);
2724 static bool
2725 bfe_reg_opr_reg (const struct instruction *insn)
2727 return bf_reg_opr_reg (insn, 0);
2730 static bool
2731 bfi_reg_opr_reg (const struct instruction *insn)
2733 return bf_reg_opr_reg (insn, 1);
2737 static bool
2738 bfe_opr_reg_reg (const struct instruction *insn)
2740 return bf_opr_reg_reg (insn, 0);
2743 static bool
2744 bfi_opr_reg_reg (const struct instruction *insn)
2746 return bf_opr_reg_reg (insn, 1);
2749 static bool
2750 bfe_reg_opr_imm (const struct instruction *insn)
2752 return bf_reg_opr_imm (insn, 0);
2755 static bool
2756 bfi_reg_opr_imm (const struct instruction *insn)
2758 return bf_reg_opr_imm (insn, 1);
2761 static bool
2762 bfe_opr_reg_imm (const struct instruction *insn)
2764 return bf_opr_reg_imm (insn, 0);
2767 static bool
2768 bfi_opr_reg_imm (const struct instruction *insn)
2770 return bf_opr_reg_imm (insn, 1);
2776 static bool
2777 tb_reg_rel (const struct instruction *insn)
2779 char *ilp = input_line_pointer;
2781 int reg;
2782 if (!lex_reg_name (REG_BIT_Dn | REG_BIT_XY, &reg))
2783 goto fail;
2785 if (!lex_match (','))
2786 goto fail;
2788 bool long_displacement;
2789 expressionS exp;
2790 if (! lex_15_bit_offset (&long_displacement, &exp))
2791 goto fail;
2793 uint8_t lb = 0x00;
2794 if (reg == REG_X || reg == REG_Y)
2796 lb |= 0x08;
2798 else
2800 lb |= reg;
2802 if (reg == REG_Y)
2803 lb |= 0x01;
2805 if (startswith (insn->name + 2, "ne"))
2806 lb |= 0x00 << 4;
2807 else if (startswith (insn->name + 2, "eq"))
2808 lb |= 0x01 << 4;
2809 else if (startswith (insn->name + 2, "pl"))
2810 lb |= 0x02 << 4;
2811 else if (startswith (insn->name + 2, "mi"))
2812 lb |= 0x03 << 4;
2813 else if (startswith (insn->name + 2, "gt"))
2814 lb |= 0x04 << 4;
2815 else if (startswith (insn->name + 2, "le"))
2816 lb |= 0x05 << 4;
2818 switch (insn->name[0])
2820 case 'd':
2821 lb |= 0x80;
2822 break;
2823 case 't':
2824 break;
2825 default:
2826 gas_assert (0);
2827 break;
2830 char *f = s12z_new_insn (long_displacement ? 4 : 3);
2831 number_to_chars_bigendian (f++, insn->opc, 1);
2832 number_to_chars_bigendian (f++, lb, 1);
2834 emit_15_bit_offset (f, 4, &exp);
2836 return true;
2838 fail:
2839 fail_line_pointer = input_line_pointer;
2840 input_line_pointer = ilp;
2841 return false;
2845 static bool
2846 tb_opr_rel (const struct instruction *insn)
2848 char *ilp = input_line_pointer;
2850 uint8_t buffer[4];
2851 int n_bytes;
2852 expressionS exp;
2853 if (!lex_opr (buffer, &n_bytes, &exp, false))
2854 goto fail;
2856 if (!lex_match (','))
2857 goto fail;
2859 bool long_displacement;
2860 expressionS exp2;
2861 if (! lex_15_bit_offset (&long_displacement, &exp2))
2862 goto fail;
2864 uint8_t lb = 0x0C;
2866 if (startswith (insn->name + 2, "ne"))
2867 lb |= 0x00 << 4;
2868 else if (startswith (insn->name + 2, "eq"))
2869 lb |= 0x01 << 4;
2870 else if (startswith (insn->name + 2, "pl"))
2871 lb |= 0x02 << 4;
2872 else if (startswith (insn->name + 2, "mi"))
2873 lb |= 0x03 << 4;
2874 else if (startswith (insn->name + 2, "gt"))
2875 lb |= 0x04 << 4;
2876 else if (startswith (insn->name + 2, "le"))
2877 lb |= 0x05 << 4;
2879 switch (insn->name[0])
2881 case 'd':
2882 lb |= 0x80;
2883 break;
2884 case 't':
2885 break;
2886 default:
2887 gas_assert (0);
2888 break;
2891 int size = size_from_suffix (insn, 0);
2893 lb |= size -1;
2895 char *f = s12z_new_insn (n_bytes + (long_displacement ? 4 : 3));
2896 number_to_chars_bigendian (f++, insn->opc, 1);
2897 number_to_chars_bigendian (f++, lb, 1);
2898 f = emit_opr (f, buffer, n_bytes, &exp);
2900 emit_15_bit_offset (f, n_bytes + 4, &exp2);
2902 return true;
2904 fail:
2905 fail_line_pointer = input_line_pointer;
2906 input_line_pointer = ilp;
2907 return false;
2913 static bool
2914 test_br_reg_reg_rel (const struct instruction *insn)
2916 char *ilp = input_line_pointer;
2918 int Di = 0;
2919 if (!lex_reg_name (REG_BIT_Dn, &Di))
2920 goto fail;
2922 if (!lex_match (','))
2923 goto fail;
2926 int Dn = 0;
2927 if (!lex_reg_name (REG_BIT_Dn, &Dn))
2928 goto fail;
2930 if (!lex_match (','))
2931 goto fail;
2934 bool long_displacement;
2935 expressionS exp;
2936 if (! lex_15_bit_offset (&long_displacement, &exp))
2937 goto fail;
2939 uint8_t bm = 0x81;
2940 uint8_t xb = 0xb8;
2942 bm |= Dn << 4;
2943 xb |= Di;
2945 char *f = s12z_new_insn (long_displacement ? 5 : 4);
2946 number_to_chars_bigendian (f++, insn->opc, 1);
2947 number_to_chars_bigendian (f++, bm, 1);
2948 number_to_chars_bigendian (f++, xb, 1);
2950 emit_15_bit_offset (f, 5, &exp);
2952 return true;
2954 fail:
2955 fail_line_pointer = input_line_pointer;
2956 input_line_pointer = ilp;
2957 return false;
2960 static bool
2961 test_br_opr_reg_rel (const struct instruction *insn)
2963 char *ilp = input_line_pointer;
2965 uint8_t buffer[4];
2966 int n_bytes;
2967 expressionS exp;
2968 if (!lex_opr (buffer, &n_bytes, &exp, false))
2969 goto fail;
2971 if (!lex_match (','))
2972 goto fail;
2974 int Dn = 0;
2975 if (!lex_reg_name (REG_BIT_Dn, &Dn))
2976 goto fail;
2978 if (!lex_match (','))
2979 goto fail;
2981 uint8_t bm = 0x81;
2982 bm |= Dn << 4;
2983 int size = size_from_suffix (insn, 0);
2984 bm |= (size -1) << 2;
2986 bool long_displacement;
2988 expressionS exp2;
2989 if (! lex_15_bit_offset (&long_displacement, &exp2))
2990 goto fail;
2992 int n = n_bytes + (long_displacement ? 4 : 3);
2993 char *f = s12z_new_insn (n);
2994 number_to_chars_bigendian (f++, insn->opc, 1);
2995 number_to_chars_bigendian (f++, bm, 1);
2996 f = emit_opr (f, buffer, n_bytes, &exp);
2998 emit_15_bit_offset (f, n, &exp2);
3000 return true;
3002 fail:
3003 fail_line_pointer = input_line_pointer;
3004 input_line_pointer = ilp;
3005 return false;
3009 static bool
3010 test_br_opr_imm_rel (const struct instruction *insn)
3012 char *ilp = input_line_pointer;
3014 uint8_t buffer[4];
3015 int n_bytes;
3016 expressionS exp;
3017 if (!lex_opr (buffer, &n_bytes, &exp, false))
3018 goto fail;
3020 if (!lex_match (','))
3021 goto fail;
3023 long imm;
3024 if (!lex_imm (&imm, NULL))
3025 goto fail;
3027 if (imm < 0 || imm > 31)
3028 goto fail;
3030 if (!lex_match (','))
3031 goto fail;
3033 bool long_displacement;
3034 expressionS exp2;
3035 if (! lex_15_bit_offset (&long_displacement, &exp2))
3036 goto fail;
3038 int size = size_from_suffix (insn, 0);
3040 uint8_t bm = 0x80;
3041 bm |= (imm & 0x07) << 4;
3042 bm |= (imm >> 3) & 0x03;
3043 if (size == 4)
3044 bm |= 0x08;
3045 else if (size == 2)
3046 bm |= 0x02;
3048 char *f = s12z_new_insn (n_bytes + (long_displacement ? 4 : 3));
3049 number_to_chars_bigendian (f++, insn->opc, 1);
3050 number_to_chars_bigendian (f++, bm, 1);
3051 f = emit_opr (f, buffer, n_bytes, &exp);
3053 emit_15_bit_offset (f, n_bytes + 4, &exp2);
3055 return true;
3057 fail:
3058 fail_line_pointer = input_line_pointer;
3059 input_line_pointer = ilp;
3060 return false;
3064 static bool
3065 test_br_reg_imm_rel (const struct instruction *insn)
3067 char *ilp = input_line_pointer;
3069 int Di = 0;
3070 if (!lex_reg_name (REG_BIT_Dn, &Di))
3071 goto fail;
3073 if (!lex_match (','))
3074 goto fail;
3076 long imm;
3077 if (!lex_imm (&imm, NULL))
3078 goto fail;
3080 if (imm < 0 || imm > 31)
3081 goto fail;
3084 if (!lex_match (','))
3085 goto fail;
3087 bool long_displacement;
3088 expressionS exp;
3089 if (! lex_15_bit_offset (&long_displacement, &exp))
3090 goto fail;
3092 uint8_t bm = Di;
3093 bm |= imm << 3;
3095 char *f = s12z_new_insn (long_displacement ? 4 : 3);
3096 number_to_chars_bigendian (f++, insn->opc, 1);
3097 number_to_chars_bigendian (f++, bm, 1);
3099 emit_15_bit_offset (f, 4, &exp);
3101 return true;
3103 fail:
3104 fail_line_pointer = input_line_pointer;
3105 input_line_pointer = ilp;
3106 return false;
3112 static const struct instruction opcodes[] = {
3113 {"bgnd", 1, 0x00, no_operands, 0},
3114 {"nop", 1, 0x01, no_operands, 0},
3116 {"brclr", 1, 0x02, test_br_reg_reg_rel, 0},
3117 {"brset", 1, 0x03, test_br_reg_reg_rel, 0},
3119 {"brclr", 1, 0x02, test_br_reg_imm_rel, 0},
3120 {"brset", 1, 0x03, test_br_reg_imm_rel, 0},
3122 {"brclr.b", 1, 0x02, test_br_opr_reg_rel, 0},
3123 {"brclr.w", 1, 0x02, test_br_opr_reg_rel, 0},
3124 {"brclr.l", 1, 0x02, test_br_opr_reg_rel, 0},
3126 {"brset.b", 1, 0x03, test_br_opr_reg_rel, 0},
3127 {"brset.w", 1, 0x03, test_br_opr_reg_rel, 0},
3128 {"brset.l", 1, 0x03, test_br_opr_reg_rel, 0},
3130 {"brclr.b", 1, 0x02, test_br_opr_imm_rel, 0},
3131 {"brclr.w", 1, 0x02, test_br_opr_imm_rel, 0},
3132 {"brclr.l", 1, 0x02, test_br_opr_imm_rel, 0},
3134 {"brset.b", 1, 0x03, test_br_opr_imm_rel, 0},
3135 {"brset.w", 1, 0x03, test_br_opr_imm_rel, 0},
3136 {"brset.l", 1, 0x03, test_br_opr_imm_rel, 0},
3138 {"psh", 1, 0x04, psh_pull, 0},
3139 {"pul", 1, 0x04, psh_pull, 0},
3141 {"rts", 1, 0x05, no_operands, 0},
3142 {"lea", 1, 0x06, reg67sxy_opr, 0},
3144 {"dbne", 1, 0x0b, tb_reg_rel, 0},
3145 {"dbeq", 1, 0x0b, tb_reg_rel, 0},
3146 {"dbpl", 1, 0x0b, tb_reg_rel, 0},
3147 {"dbmi", 1, 0x0b, tb_reg_rel, 0},
3148 {"dbgt", 1, 0x0b, tb_reg_rel, 0},
3149 {"dble", 1, 0x0b, tb_reg_rel, 0},
3151 {"dbne.b", 1, 0x0b, tb_opr_rel, 0},
3152 {"dbeq.b", 1, 0x0b, tb_opr_rel, 0},
3153 {"dbpl.b", 1, 0x0b, tb_opr_rel, 0},
3154 {"dbmi.b", 1, 0x0b, tb_opr_rel, 0},
3155 {"dbgt.b", 1, 0x0b, tb_opr_rel, 0},
3156 {"dble.b", 1, 0x0b, tb_opr_rel, 0},
3158 {"dbne.w", 1, 0x0b, tb_opr_rel, 0},
3159 {"dbeq.w", 1, 0x0b, tb_opr_rel, 0},
3160 {"dbpl.w", 1, 0x0b, tb_opr_rel, 0},
3161 {"dbmi.w", 1, 0x0b, tb_opr_rel, 0},
3162 {"dbgt.w", 1, 0x0b, tb_opr_rel, 0},
3163 {"dble.w", 1, 0x0b, tb_opr_rel, 0},
3165 {"dbne.p", 1, 0x0b, tb_opr_rel, 0},
3166 {"dbeq.p", 1, 0x0b, tb_opr_rel, 0},
3167 {"dbpl.p", 1, 0x0b, tb_opr_rel, 0},
3168 {"dbmi.p", 1, 0x0b, tb_opr_rel, 0},
3169 {"dbgt.p", 1, 0x0b, tb_opr_rel, 0},
3170 {"dble.p", 1, 0x0b, tb_opr_rel, 0},
3172 {"dbne.l", 1, 0x0b, tb_opr_rel, 0},
3173 {"dbeq.l", 1, 0x0b, tb_opr_rel, 0},
3174 {"dbpl.l", 1, 0x0b, tb_opr_rel, 0},
3175 {"dbmi.l", 1, 0x0b, tb_opr_rel, 0},
3176 {"dbgt.l", 1, 0x0b, tb_opr_rel, 0},
3177 {"dble.l", 1, 0x0b, tb_opr_rel, 0},
3179 {"tbne", 1, 0x0b, tb_reg_rel, 0},
3180 {"tbeq", 1, 0x0b, tb_reg_rel, 0},
3181 {"tbpl", 1, 0x0b, tb_reg_rel, 0},
3182 {"tbmi", 1, 0x0b, tb_reg_rel, 0},
3183 {"tbgt", 1, 0x0b, tb_reg_rel, 0},
3184 {"tble", 1, 0x0b, tb_reg_rel, 0},
3186 {"tbne.b", 1, 0x0b, tb_opr_rel, 0},
3187 {"tbeq.b", 1, 0x0b, tb_opr_rel, 0},
3188 {"tbpl.b", 1, 0x0b, tb_opr_rel, 0},
3189 {"tbmi.b", 1, 0x0b, tb_opr_rel, 0},
3190 {"tbgt.b", 1, 0x0b, tb_opr_rel, 0},
3191 {"tble.b", 1, 0x0b, tb_opr_rel, 0},
3193 {"tbne.w", 1, 0x0b, tb_opr_rel, 0},
3194 {"tbeq.w", 1, 0x0b, tb_opr_rel, 0},
3195 {"tbpl.w", 1, 0x0b, tb_opr_rel, 0},
3196 {"tbmi.w", 1, 0x0b, tb_opr_rel, 0},
3197 {"tbgt.w", 1, 0x0b, tb_opr_rel, 0},
3198 {"tble.w", 1, 0x0b, tb_opr_rel, 0},
3200 {"tbne.p", 1, 0x0b, tb_opr_rel, 0},
3201 {"tbeq.p", 1, 0x0b, tb_opr_rel, 0},
3202 {"tbpl.p", 1, 0x0b, tb_opr_rel, 0},
3203 {"tbmi.p", 1, 0x0b, tb_opr_rel, 0},
3204 {"tbgt.p", 1, 0x0b, tb_opr_rel, 0},
3205 {"tble.p", 1, 0x0b, tb_opr_rel, 0},
3207 {"tbne.l", 1, 0x0b, tb_opr_rel, 0},
3208 {"tbeq.l", 1, 0x0b, tb_opr_rel, 0},
3209 {"tbpl.l", 1, 0x0b, tb_opr_rel, 0},
3210 {"tbmi.l", 1, 0x0b, tb_opr_rel, 0},
3211 {"tbgt.l", 1, 0x0b, tb_opr_rel, 0},
3212 {"tble.l", 1, 0x0b, tb_opr_rel, 0},
3214 {"mov.b", 1, 0x0c, imm_opr, 0},
3215 {"mov.w", 1, 0x0d, imm_opr, 0},
3216 {"mov.p", 1, 0x0e, imm_opr, 0},
3217 {"mov.l", 1, 0x0f, imm_opr, 0},
3219 {"rol", 1, 0x10, rol, 0},
3220 {"rol.b", 1, 0x10, rol, 0},
3221 {"rol.w", 1, 0x10, rol, 0},
3222 {"rol.p", 1, 0x10, rol, 0},
3223 {"rol.l", 1, 0x10, rol, 0},
3225 {"ror", 1, 0x10, ror, 0},
3226 {"ror.b", 1, 0x10, ror, 0},
3227 {"ror.w", 1, 0x10, ror, 0},
3228 {"ror.p", 1, 0x10, ror, 0},
3229 {"ror.l", 1, 0x10, ror, 0},
3231 {"lsl", 1, 0x10, shift_reg, 0},
3232 {"lsr", 1, 0x10, shift_reg, 0},
3233 {"asl", 1, 0x10, shift_reg, 0},
3234 {"asr", 1, 0x10, shift_reg, 0},
3236 {"lsl.b", 1, 0x10, shift_two_operand, 0},
3237 {"lsl.w", 1, 0x10, shift_two_operand, 0},
3238 {"lsl.p", 1, 0x10, shift_two_operand, 0},
3239 {"lsl.l", 1, 0x10, shift_two_operand, 0},
3240 {"asl.b", 1, 0x10, shift_two_operand, 0},
3241 {"asl.w", 1, 0x10, shift_two_operand, 0},
3242 {"asl.p", 1, 0x10, shift_two_operand, 0},
3243 {"asl.l", 1, 0x10, shift_two_operand, 0},
3245 {"lsr.b", 1, 0x10, shift_two_operand, 0},
3246 {"lsr.w", 1, 0x10, shift_two_operand, 0},
3247 {"lsr.p", 1, 0x10, shift_two_operand, 0},
3248 {"lsr.l", 1, 0x10, shift_two_operand, 0},
3249 {"asr.b", 1, 0x10, shift_two_operand, 0},
3250 {"asr.w", 1, 0x10, shift_two_operand, 0},
3251 {"asr.p", 1, 0x10, shift_two_operand, 0},
3252 {"asr.l", 1, 0x10, shift_two_operand, 0},
3254 {"lsl.b", 1, 0x10, shift_opr_imm, 0},
3255 {"lsl.w", 1, 0x10, shift_opr_imm, 0},
3256 {"lsl.p", 1, 0x10, shift_opr_imm, 0},
3257 {"lsl.l", 1, 0x10, shift_opr_imm, 0},
3258 {"asl.b", 1, 0x10, shift_opr_imm, 0},
3259 {"asl.w", 1, 0x10, shift_opr_imm, 0},
3260 {"asl.p", 1, 0x10, shift_opr_imm, 0},
3261 {"asl.l", 1, 0x10, shift_opr_imm, 0},
3263 {"lsr.b", 1, 0x10, shift_opr_imm, 0},
3264 {"lsr.w", 1, 0x10, shift_opr_imm, 0},
3265 {"lsr.p", 1, 0x10, shift_opr_imm, 0},
3266 {"lsr.l", 1, 0x10, shift_opr_imm, 0},
3267 {"asr.b", 1, 0x10, shift_opr_imm, 0},
3268 {"asr.w", 1, 0x10, shift_opr_imm, 0},
3269 {"asr.p", 1, 0x10, shift_opr_imm, 0},
3270 {"asr.l", 1, 0x10, shift_opr_imm, 0},
3272 {"mov.b", 1, 0x1c, opr_opr, 0},
3273 {"mov.w", 1, 0x1d, opr_opr, 0},
3274 {"mov.p", 1, 0x1e, opr_opr, 0},
3275 {"mov.l", 1, 0x1f, opr_opr, 0},
3277 {"bra", 1, 0x20, rel, 0},
3278 {"bsr", 1, 0x21, rel, 0},
3279 {"bhi", 1, 0x22, rel, 0},
3280 {"bls", 1, 0x23, rel, 0},
3281 {"bcc", 1, 0x24, rel, 0},
3282 {"bhs", 1, 0x24, rel, 0}, /* Alias for bcc */
3283 {"bcs", 1, 0x25, rel, 0},
3284 {"blo", 1, 0x25, rel, 0}, /* Alias for bcs */
3285 {"bne", 1, 0x26, rel, 0},
3286 {"beq", 1, 0x27, rel, 0},
3287 {"bvc", 1, 0x28, rel, 0},
3288 {"bvs", 1, 0x29, rel, 0},
3289 {"bpl", 1, 0x2a, rel, 0},
3290 {"bmi", 1, 0x2b, rel, 0},
3291 {"bge", 1, 0x2c, rel, 0},
3292 {"blt", 1, 0x2d, rel, 0},
3293 {"bgt", 1, 0x2e, rel, 0},
3294 {"ble", 1, 0x2f, rel, 0},
3296 {"inc", 1, 0x30, reg_inh, 0},
3297 {"clr", 1, 0x38, reg_inh, 0},
3298 {"dec", 1, 0x40, reg_inh, 0},
3300 {"muls", 1, 0x48, mul_reg_reg_reg, 0},
3301 {"mulu", 1, 0x48, mul_reg_reg_reg, 0},
3303 {"muls.b", 1, 0x48, mul_reg_reg_opr, 0},
3304 {"muls.w", 1, 0x48, mul_reg_reg_opr, 0},
3305 {"muls.l", 1, 0x48, mul_reg_reg_opr, 0},
3307 {"mulu.b", 1, 0x48, mul_reg_reg_opr, 0},
3308 {"mulu.w", 1, 0x48, mul_reg_reg_opr, 0},
3309 {"mulu.l", 1, 0x48, mul_reg_reg_opr, 0},
3311 {"muls.b", 1, 0x48, mul_reg_reg_imm, 0},
3312 {"muls.w", 1, 0x48, mul_reg_reg_imm, 0},
3313 {"muls.l", 1, 0x48, mul_reg_reg_imm, 0},
3315 {"mulu.b", 1, 0x48, mul_reg_reg_imm, 0},
3316 {"mulu.w", 1, 0x48, mul_reg_reg_imm, 0},
3317 {"mulu.l", 1, 0x48, mul_reg_reg_imm, 0},
3319 {"muls.bb", 1, 0x48, mul_reg_opr_opr, 0},
3320 {"muls.bw", 1, 0x48, mul_reg_opr_opr, 0},
3321 {"muls.bp", 1, 0x48, mul_reg_opr_opr, 0},
3322 {"muls.bl", 1, 0x48, mul_reg_opr_opr, 0},
3324 {"muls.wb", 1, 0x48, mul_reg_opr_opr, 0},
3325 {"muls.ww", 1, 0x48, mul_reg_opr_opr, 0},
3326 {"muls.wp", 1, 0x48, mul_reg_opr_opr, 0},
3327 {"muls.wl", 1, 0x48, mul_reg_opr_opr, 0},
3329 {"muls.pb", 1, 0x48, mul_reg_opr_opr, 0},
3330 {"muls.pw", 1, 0x48, mul_reg_opr_opr, 0},
3331 {"muls.pp", 1, 0x48, mul_reg_opr_opr, 0},
3332 {"muls.pl", 1, 0x48, mul_reg_opr_opr, 0},
3334 {"muls.lb", 1, 0x48, mul_reg_opr_opr, 0},
3335 {"muls.lw", 1, 0x48, mul_reg_opr_opr, 0},
3336 {"muls.lp", 1, 0x48, mul_reg_opr_opr, 0},
3337 {"muls.ll", 1, 0x48, mul_reg_opr_opr, 0},
3339 {"mulu.bb", 1, 0x48, mul_reg_opr_opr, 0},
3340 {"mulu.bw", 1, 0x48, mul_reg_opr_opr, 0},
3341 {"mulu.bp", 1, 0x48, mul_reg_opr_opr, 0},
3342 {"mulu.bl", 1, 0x48, mul_reg_opr_opr, 0},
3344 {"mulu.wb", 1, 0x48, mul_reg_opr_opr, 0},
3345 {"mulu.ww", 1, 0x48, mul_reg_opr_opr, 0},
3346 {"mulu.wp", 1, 0x48, mul_reg_opr_opr, 0},
3347 {"mulu.wl", 1, 0x48, mul_reg_opr_opr, 0},
3349 {"mulu.pb", 1, 0x48, mul_reg_opr_opr, 0},
3350 {"mulu.pw", 1, 0x48, mul_reg_opr_opr, 0},
3351 {"mulu.pp", 1, 0x48, mul_reg_opr_opr, 0},
3352 {"mulu.pl", 1, 0x48, mul_reg_opr_opr, 0},
3354 {"mulu.lb", 1, 0x48, mul_reg_opr_opr, 0},
3355 {"mulu.lw", 1, 0x48, mul_reg_opr_opr, 0},
3356 {"mulu.lp", 1, 0x48, mul_reg_opr_opr, 0},
3357 {"mulu.ll", 1, 0x48, mul_reg_opr_opr, 0},
3359 {"add", 1, 0x50, regd_imm, 0},
3360 {"and", 1, 0x58, regd_imm, 0},
3362 {"add", 1, 0x60, regd_opr, 0},
3363 {"and", 1, 0x68, regd_opr, 0},
3365 {"sub", 1, 0x70, regd_imm, 0},
3366 {"or", 1, 0x78, regd_imm, 0},
3368 {"sub", 1, 0x80, regd_opr, 0},
3369 {"or", 1, 0x88, regd_opr, 0},
3371 {"ld", 1, 0x90, regdxy_imm, 0},
3373 {"clr", 1, 0x9a, clr_xy, 0},
3374 {"tfr", 1, 0x9e, tfr, 0},
3375 {"zex", 1, 0x9e, tfr, 0},
3377 {"ld", 1, 0xa0, regdxy_opr_src, 0xb0},
3379 {"jmp", 1, 0xaa, opr, 0xba},
3380 {"jsr", 1, 0xab, opr, 0xbb},
3382 {"exg", 1, 0xae, tfr, 0},
3383 {"sex", 1, 0xae, tfr, 0},
3385 {"st", 1, 0xc0, regdxy_opr_dest, 0xd0},
3387 {"andcc", 1, 0xce, imm8, 0},
3388 {"orcc", 1, 0xde, imm8, 0},
3390 {"inc.b", 1, 0x9c, opr, 0},
3391 {"inc.w", 1, 0x9d, opr, 0},
3392 {"inc.l", 1, 0x9f, opr, 0},
3394 {"dec.b", 1, 0xac, opr, 0},
3395 {"dec.w", 1, 0xad, opr, 0},
3396 {"dec.l", 1, 0xaf, opr, 0},
3398 {"clr.b", 1, 0xbc, opr, 0},
3399 {"clr.w", 1, 0xbd, opr, 0},
3400 {"clr.p", 1, 0xbe, opr, 0},
3401 {"clr.l", 1, 0xbf, opr, 0},
3403 {"com.b", 1, 0xcc, opr, 0},
3404 {"com.w", 1, 0xcd, opr, 0},
3405 {"com.l", 1, 0xcf, opr, 0},
3407 {"neg.b", 1, 0xdc, opr, 0},
3408 {"neg.w", 1, 0xdd, opr, 0},
3409 {"neg.l", 1, 0xdf, opr, 0},
3411 {"bclr", 1, 0xec, bm_regd_imm, 0},
3412 {"bset", 1, 0xed, bm_regd_imm, 0},
3413 {"btgl", 1, 0xee, bm_regd_imm, 0},
3415 {"bclr", 1, 0xec, bm_regd_reg, 0},
3416 {"bset", 1, 0xed, bm_regd_reg, 0},
3417 {"btgl", 1, 0xee, bm_regd_reg, 0},
3419 {"bclr.b", 1, 0xec, bm_opr_imm, 0},
3420 {"bclr.w", 1, 0xec, bm_opr_imm, 0},
3421 {"bclr.l", 1, 0xec, bm_opr_imm, 0},
3423 {"bset.b", 1, 0xed, bm_opr_imm, 0},
3424 {"bset.w", 1, 0xed, bm_opr_imm, 0},
3425 {"bset.l", 1, 0xed, bm_opr_imm, 0},
3427 {"btgl.b", 1, 0xee, bm_opr_imm, 0},
3428 {"btgl.w", 1, 0xee, bm_opr_imm, 0},
3429 {"btgl.l", 1, 0xee, bm_opr_imm, 0},
3431 {"bclr.b", 1, 0xec, bm_opr_reg, 0},
3432 {"bclr.w", 1, 0xec, bm_opr_reg, 0},
3433 {"bclr.l", 1, 0xec, bm_opr_reg, 0},
3435 {"bset.b", 1, 0xed, bm_opr_reg, 0},
3436 {"bset.w", 1, 0xed, bm_opr_reg, 0},
3437 {"bset.l", 1, 0xed, bm_opr_reg, 0},
3439 {"btgl.b", 1, 0xee, bm_opr_reg, 0},
3440 {"btgl.w", 1, 0xee, bm_opr_reg, 0},
3441 {"btgl.l", 1, 0xee, bm_opr_reg, 0},
3443 {"cmp", 1, 0xe0, regdxy_imm, 0},
3444 {"cmp", 1, 0xf0, regdxy_opr_src, 0},
3446 {"cmp", 1, 0xfc, regx_regy, 0},
3447 {"sub", 1, 0xfd, regd6_regx_regy, 0},
3448 {"sub", 1, 0xfe, regd6_regy_regx, 0},
3450 {"swi", 1, 0xff, no_operands, 0},
3452 /* Page 2 */
3454 /* The -10 below is a kludge. The opcode is in fact 0x00 */
3455 {"ld", 2, -10, regs_opr_src, 0},
3457 /* The -9 below is a kludge. The opcode is in fact 0x01 */
3458 {"st", 2, -9, regs_opr_dest, 0},
3460 /* The -8 below is a kludge. The opcode is in fact 0x02 */
3461 {"cmp", 2, -8, regs_opr_src, 0},
3463 /* The -7 below is a kludge. The opcode is in fact 0x03 */
3464 {"ld", 2, -7, regs_imm, 0},
3466 /* The -6 below is a kludge. The opcode is in fact 0x04 */
3467 {"cmp", 2, -6, regs_imm, 0},
3469 {"bfext", 2, 0x08, bfe_reg_reg_reg, 0},
3470 {"bfext", 2, 0x08, bfe_reg_reg_imm, 0},
3471 {"bfext.b", 2, 0x08, bfe_reg_opr_reg, 0},
3472 {"bfext.w", 2, 0x08, bfe_reg_opr_reg, 0},
3473 {"bfext.p", 2, 0x08, bfe_reg_opr_reg, 0},
3474 {"bfext.l", 2, 0x08, bfe_reg_opr_reg, 0},
3475 {"bfext.b", 2, 0x08, bfe_opr_reg_reg, 0},
3476 {"bfext.w", 2, 0x08, bfe_opr_reg_reg, 0},
3477 {"bfext.p", 2, 0x08, bfe_opr_reg_reg, 0},
3478 {"bfext.l", 2, 0x08, bfe_opr_reg_reg, 0},
3479 {"bfext.b", 2, 0x08, bfe_reg_opr_imm, 0},
3480 {"bfext.w", 2, 0x08, bfe_reg_opr_imm, 0},
3481 {"bfext.p", 2, 0x08, bfe_reg_opr_imm, 0},
3482 {"bfext.l", 2, 0x08, bfe_reg_opr_imm, 0},
3483 {"bfext.b", 2, 0x08, bfe_opr_reg_imm, 0},
3484 {"bfext.w", 2, 0x08, bfe_opr_reg_imm, 0},
3485 {"bfext.p", 2, 0x08, bfe_opr_reg_imm, 0},
3486 {"bfext.l", 2, 0x08, bfe_opr_reg_imm, 0},
3489 {"bfins", 2, 0x08, bfi_reg_reg_reg, 0},
3490 {"bfins", 2, 0x08, bfi_reg_reg_imm, 0},
3491 {"bfins.b", 2, 0x08, bfi_reg_opr_reg, 0},
3492 {"bfins.w", 2, 0x08, bfi_reg_opr_reg, 0},
3493 {"bfins.p", 2, 0x08, bfi_reg_opr_reg, 0},
3494 {"bfins.l", 2, 0x08, bfi_reg_opr_reg, 0},
3495 {"bfins.b", 2, 0x08, bfi_opr_reg_reg, 0},
3496 {"bfins.w", 2, 0x08, bfi_opr_reg_reg, 0},
3497 {"bfins.p", 2, 0x08, bfi_opr_reg_reg, 0},
3498 {"bfins.l", 2, 0x08, bfi_opr_reg_reg, 0},
3499 {"bfins.b", 2, 0x08, bfi_reg_opr_imm, 0},
3500 {"bfins.w", 2, 0x08, bfi_reg_opr_imm, 0},
3501 {"bfins.p", 2, 0x08, bfi_reg_opr_imm, 0},
3502 {"bfins.l", 2, 0x08, bfi_reg_opr_imm, 0},
3503 {"bfins.b", 2, 0x08, bfi_opr_reg_imm, 0},
3504 {"bfins.w", 2, 0x08, bfi_opr_reg_imm, 0},
3505 {"bfins.p", 2, 0x08, bfi_opr_reg_imm, 0},
3506 {"bfins.l", 2, 0x08, bfi_opr_reg_imm, 0},
3509 {"minu", 2, 0x10, regd_opr, 0},
3510 {"maxu", 2, 0x18, regd_opr, 0},
3511 {"mins", 2, 0x20, regd_opr, 0},
3512 {"maxs", 2, 0x28, regd_opr, 0},
3514 {"clb", 2, 0x91, tfr, 0},
3516 {"trap", 2, 0x00, trap_imm, 0},
3517 {"abs", 2, 0x40, reg_inh, 0},
3518 {"sat", 2, 0xa0, reg_inh, 0},
3520 {"rti", 2, 0x90, no_operands, 0},
3521 {"stop", 2, 0x05, no_operands, 0},
3522 {"wai", 2, 0x06, no_operands, 0},
3523 {"sys", 2, 0x07, no_operands, 0},
3525 {"bit", 2, 0x58, regd_imm, 0},
3526 {"bit", 2, 0x68, regd_opr, 0},
3528 {"adc", 2, 0x50, regd_imm, 0},
3529 {"adc", 2, 0x60, regd_opr, 0},
3531 {"sbc", 2, 0x70, regd_imm, 0},
3532 {"eor", 2, 0x78, regd_imm, 0},
3534 {"sbc", 2, 0x80, regd_opr, 0},
3535 {"eor", 2, 0x88, regd_opr, 0},
3537 {"divs", 2, 0x30, mul_reg_reg_reg, 0},
3538 {"divu", 2, 0x30, mul_reg_reg_reg, 0},
3540 {"divs.b", 2, 0x30, mul_reg_reg_opr, 0},
3541 {"divs.w", 2, 0x30, mul_reg_reg_opr, 0},
3542 {"divs.l", 2, 0x30, mul_reg_reg_opr, 0},
3544 {"divu.b", 2, 0x30, mul_reg_reg_opr, 0},
3545 {"divu.w", 2, 0x30, mul_reg_reg_opr, 0},
3546 {"divu.l", 2, 0x30, mul_reg_reg_opr, 0},
3548 {"divs.b", 2, 0x30, mul_reg_reg_imm, 0},
3549 {"divs.w", 2, 0x30, mul_reg_reg_imm, 0},
3550 {"divs.l", 2, 0x30, mul_reg_reg_imm, 0},
3552 {"divu.b", 2, 0x30, mul_reg_reg_imm, 0},
3553 {"divu.w", 2, 0x30, mul_reg_reg_imm, 0},
3554 {"divu.l", 2, 0x30, mul_reg_reg_imm, 0},
3556 {"divs.bb", 2, 0x30, mul_reg_opr_opr, 0},
3557 {"divs.bw", 2, 0x30, mul_reg_opr_opr, 0},
3558 {"divs.bp", 2, 0x30, mul_reg_opr_opr, 0},
3559 {"divs.bl", 2, 0x30, mul_reg_opr_opr, 0},
3561 {"divs.wb", 2, 0x30, mul_reg_opr_opr, 0},
3562 {"divs.ww", 2, 0x30, mul_reg_opr_opr, 0},
3563 {"divs.wp", 2, 0x30, mul_reg_opr_opr, 0},
3564 {"divs.wl", 2, 0x30, mul_reg_opr_opr, 0},
3566 {"divs.pb", 2, 0x30, mul_reg_opr_opr, 0},
3567 {"divs.pw", 2, 0x30, mul_reg_opr_opr, 0},
3568 {"divs.pp", 2, 0x30, mul_reg_opr_opr, 0},
3569 {"divs.pl", 2, 0x30, mul_reg_opr_opr, 0},
3571 {"divs.lb", 2, 0x30, mul_reg_opr_opr, 0},
3572 {"divs.lw", 2, 0x30, mul_reg_opr_opr, 0},
3573 {"divs.lp", 2, 0x30, mul_reg_opr_opr, 0},
3574 {"divs.ll", 2, 0x30, mul_reg_opr_opr, 0},
3576 {"divu.bb", 2, 0x30, mul_reg_opr_opr, 0},
3577 {"divu.bw", 2, 0x30, mul_reg_opr_opr, 0},
3578 {"divu.bp", 2, 0x30, mul_reg_opr_opr, 0},
3579 {"divu.bl", 2, 0x30, mul_reg_opr_opr, 0},
3581 {"divu.wb", 2, 0x30, mul_reg_opr_opr, 0},
3582 {"divu.ww", 2, 0x30, mul_reg_opr_opr, 0},
3583 {"divu.wp", 2, 0x30, mul_reg_opr_opr, 0},
3584 {"divu.wl", 2, 0x30, mul_reg_opr_opr, 0},
3586 {"divu.pb", 2, 0x30, mul_reg_opr_opr, 0},
3587 {"divu.pw", 2, 0x30, mul_reg_opr_opr, 0},
3588 {"divu.pp", 2, 0x30, mul_reg_opr_opr, 0},
3589 {"divu.pl", 2, 0x30, mul_reg_opr_opr, 0},
3591 {"divu.lb", 2, 0x30, mul_reg_opr_opr, 0},
3592 {"divu.lw", 2, 0x30, mul_reg_opr_opr, 0},
3593 {"divu.lp", 2, 0x30, mul_reg_opr_opr, 0},
3594 {"divu.ll", 2, 0x30, mul_reg_opr_opr, 0},
3596 {"qmuls", 2, 0xb0, mul_reg_reg_reg, 0},
3597 {"qmulu", 2, 0xb0, mul_reg_reg_reg, 0},
3599 {"qmuls.b", 2, 0xb0, mul_reg_reg_opr, 0},
3600 {"qmuls.w", 2, 0xb0, mul_reg_reg_opr, 0},
3601 {"qmuls.l", 2, 0xb0, mul_reg_reg_opr, 0},
3603 {"qmulu.b", 2, 0xb0, mul_reg_reg_opr, 0},
3604 {"qmulu.w", 2, 0xb0, mul_reg_reg_opr, 0},
3605 {"qmulu.l", 2, 0xb0, mul_reg_reg_opr, 0},
3607 {"qmuls.b", 2, 0xb0, mul_reg_reg_imm, 0},
3608 {"qmuls.w", 2, 0xb0, mul_reg_reg_imm, 0},
3609 {"qmuls.l", 2, 0xb0, mul_reg_reg_imm, 0},
3611 {"qmulu.b", 2, 0xb0, mul_reg_reg_imm, 0},
3612 {"qmulu.w", 2, 0xb0, mul_reg_reg_imm, 0},
3613 {"qmulu.l", 2, 0xb0, mul_reg_reg_imm, 0},
3615 {"qmuls.bb", 2, 0xb0, mul_reg_opr_opr, 0},
3616 {"qmuls.bw", 2, 0xb0, mul_reg_opr_opr, 0},
3617 {"qmuls.bp", 2, 0xb0, mul_reg_opr_opr, 0},
3618 {"qmuls.bl", 2, 0xb0, mul_reg_opr_opr, 0},
3620 {"qmuls.wb", 2, 0xb0, mul_reg_opr_opr, 0},
3621 {"qmuls.ww", 2, 0xb0, mul_reg_opr_opr, 0},
3622 {"qmuls.wp", 2, 0xb0, mul_reg_opr_opr, 0},
3623 {"qmuls.wl", 2, 0xb0, mul_reg_opr_opr, 0},
3625 {"qmuls.pb", 2, 0xb0, mul_reg_opr_opr, 0},
3626 {"qmuls.pw", 2, 0xb0, mul_reg_opr_opr, 0},
3627 {"qmuls.pp", 2, 0xb0, mul_reg_opr_opr, 0},
3628 {"qmuls.pl", 2, 0xb0, mul_reg_opr_opr, 0},
3630 {"qmuls.lb", 2, 0xb0, mul_reg_opr_opr, 0},
3631 {"qmuls.lw", 2, 0xb0, mul_reg_opr_opr, 0},
3632 {"qmuls.lp", 2, 0xb0, mul_reg_opr_opr, 0},
3633 {"qmuls.ll", 2, 0xb0, mul_reg_opr_opr, 0},
3635 {"qmulu.bb", 2, 0xb0, mul_reg_opr_opr, 0},
3636 {"qmulu.bw", 2, 0xb0, mul_reg_opr_opr, 0},
3637 {"qmulu.bp", 2, 0xb0, mul_reg_opr_opr, 0},
3638 {"qmulu.bl", 2, 0xb0, mul_reg_opr_opr, 0},
3640 {"qmulu.wb", 2, 0xb0, mul_reg_opr_opr, 0},
3641 {"qmulu.ww", 2, 0xb0, mul_reg_opr_opr, 0},
3642 {"qmulu.wp", 2, 0xb0, mul_reg_opr_opr, 0},
3643 {"qmulu.wl", 2, 0xb0, mul_reg_opr_opr, 0},
3645 {"qmulu.pb", 2, 0xb0, mul_reg_opr_opr, 0},
3646 {"qmulu.pw", 2, 0xb0, mul_reg_opr_opr, 0},
3647 {"qmulu.pp", 2, 0xb0, mul_reg_opr_opr, 0},
3648 {"qmulu.pl", 2, 0xb0, mul_reg_opr_opr, 0},
3650 {"qmulu.lb", 2, 0xb0, mul_reg_opr_opr, 0},
3651 {"qmulu.lw", 2, 0xb0, mul_reg_opr_opr, 0},
3652 {"qmulu.lp", 2, 0xb0, mul_reg_opr_opr, 0},
3653 {"qmulu.ll", 2, 0xb0, mul_reg_opr_opr, 0},
3655 {"macs", 2, 0x48, mul_reg_reg_reg, 0},
3656 {"macu", 2, 0x48, mul_reg_reg_reg, 0},
3658 {"macs.b", 2, 0x48, mul_reg_reg_opr, 0},
3659 {"macs.w", 2, 0x48, mul_reg_reg_opr, 0},
3660 {"macs.l", 2, 0x48, mul_reg_reg_opr, 0},
3662 {"macu.b", 2, 0x48, mul_reg_reg_opr, 0},
3663 {"macu.w", 2, 0x48, mul_reg_reg_opr, 0},
3664 {"macu.l", 2, 0x48, mul_reg_reg_opr, 0},
3666 {"macs.b", 2, 0x48, mul_reg_reg_imm, 0},
3667 {"macs.w", 2, 0x48, mul_reg_reg_imm, 0},
3668 {"macs.l", 2, 0x48, mul_reg_reg_imm, 0},
3670 {"macu.b", 2, 0x48, mul_reg_reg_imm, 0},
3671 {"macu.w", 2, 0x48, mul_reg_reg_imm, 0},
3672 {"macu.l", 2, 0x48, mul_reg_reg_imm, 0},
3674 {"macs.bb", 2, 0x48, mul_reg_opr_opr, 0},
3675 {"macs.bw", 2, 0x48, mul_reg_opr_opr, 0},
3676 {"macs.bp", 2, 0x48, mul_reg_opr_opr, 0},
3677 {"macs.bl", 2, 0x48, mul_reg_opr_opr, 0},
3679 {"macs.wb", 2, 0x48, mul_reg_opr_opr, 0},
3680 {"macs.ww", 2, 0x48, mul_reg_opr_opr, 0},
3681 {"macs.wp", 2, 0x48, mul_reg_opr_opr, 0},
3682 {"macs.wl", 2, 0x48, mul_reg_opr_opr, 0},
3684 {"macs.pb", 2, 0x48, mul_reg_opr_opr, 0},
3685 {"macs.pw", 2, 0x48, mul_reg_opr_opr, 0},
3686 {"macs.pp", 2, 0x48, mul_reg_opr_opr, 0},
3687 {"macs.pl", 2, 0x48, mul_reg_opr_opr, 0},
3689 {"macs.lb", 2, 0x48, mul_reg_opr_opr, 0},
3690 {"macs.lw", 2, 0x48, mul_reg_opr_opr, 0},
3691 {"macs.lp", 2, 0x48, mul_reg_opr_opr, 0},
3692 {"macs.ll", 2, 0x48, mul_reg_opr_opr, 0},
3694 {"macu.bb", 2, 0x48, mul_reg_opr_opr, 0},
3695 {"macu.bw", 2, 0x48, mul_reg_opr_opr, 0},
3696 {"macu.bp", 2, 0x48, mul_reg_opr_opr, 0},
3697 {"macu.bl", 2, 0x48, mul_reg_opr_opr, 0},
3699 {"macu.wb", 2, 0x48, mul_reg_opr_opr, 0},
3700 {"macu.ww", 2, 0x48, mul_reg_opr_opr, 0},
3701 {"macu.wp", 2, 0x48, mul_reg_opr_opr, 0},
3702 {"macu.wl", 2, 0x48, mul_reg_opr_opr, 0},
3704 {"macu.pb", 2, 0x48, mul_reg_opr_opr, 0},
3705 {"macu.pw", 2, 0x48, mul_reg_opr_opr, 0},
3706 {"macu.pp", 2, 0x48, mul_reg_opr_opr, 0},
3707 {"macu.pl", 2, 0x48, mul_reg_opr_opr, 0},
3709 {"macu.lb", 2, 0x48, mul_reg_opr_opr, 0},
3710 {"macu.lw", 2, 0x48, mul_reg_opr_opr, 0},
3711 {"macu.lp", 2, 0x48, mul_reg_opr_opr, 0},
3712 {"macu.ll", 2, 0x48, mul_reg_opr_opr, 0},
3714 {"mods", 2, 0x38, mul_reg_reg_reg, 0},
3715 {"modu", 2, 0x38, mul_reg_reg_reg, 0},
3717 {"mods.b", 2, 0x38, mul_reg_reg_opr, 0},
3718 {"mods.w", 2, 0x38, mul_reg_reg_opr, 0},
3719 {"mods.l", 2, 0x38, mul_reg_reg_opr, 0},
3721 {"modu.b", 2, 0x38, mul_reg_reg_opr, 0},
3722 {"modu.w", 2, 0x38, mul_reg_reg_opr, 0},
3723 {"modu.l", 2, 0x38, mul_reg_reg_opr, 0},
3725 {"mods.b", 2, 0x38, mul_reg_reg_imm, 0},
3726 {"mods.w", 2, 0x38, mul_reg_reg_imm, 0},
3727 {"mods.l", 2, 0x38, mul_reg_reg_imm, 0},
3729 {"modu.b", 2, 0x38, mul_reg_reg_imm, 0},
3730 {"modu.w", 2, 0x38, mul_reg_reg_imm, 0},
3731 {"modu.l", 2, 0x38, mul_reg_reg_imm, 0},
3733 {"mods.bb", 2, 0x38, mul_reg_opr_opr, 0},
3734 {"mods.bw", 2, 0x38, mul_reg_opr_opr, 0},
3735 {"mods.bp", 2, 0x38, mul_reg_opr_opr, 0},
3736 {"mods.bl", 2, 0x38, mul_reg_opr_opr, 0},
3738 {"mods.wb", 2, 0x38, mul_reg_opr_opr, 0},
3739 {"mods.ww", 2, 0x38, mul_reg_opr_opr, 0},
3740 {"mods.wp", 2, 0x38, mul_reg_opr_opr, 0},
3741 {"mods.wl", 2, 0x38, mul_reg_opr_opr, 0},
3743 {"mods.pb", 2, 0x38, mul_reg_opr_opr, 0},
3744 {"mods.pw", 2, 0x38, mul_reg_opr_opr, 0},
3745 {"mods.pp", 2, 0x38, mul_reg_opr_opr, 0},
3746 {"mods.pl", 2, 0x38, mul_reg_opr_opr, 0},
3748 {"mods.lb", 2, 0x38, mul_reg_opr_opr, 0},
3749 {"mods.lw", 2, 0x38, mul_reg_opr_opr, 0},
3750 {"mods.lp", 2, 0x38, mul_reg_opr_opr, 0},
3751 {"mods.ll", 2, 0x38, mul_reg_opr_opr, 0},
3753 {"modu.bb", 2, 0x38, mul_reg_opr_opr, 0},
3754 {"modu.bw", 2, 0x38, mul_reg_opr_opr, 0},
3755 {"modu.bp", 2, 0x38, mul_reg_opr_opr, 0},
3756 {"modu.bl", 2, 0x38, mul_reg_opr_opr, 0},
3758 {"modu.wb", 2, 0x38, mul_reg_opr_opr, 0},
3759 {"modu.ww", 2, 0x38, mul_reg_opr_opr, 0},
3760 {"modu.wp", 2, 0x38, mul_reg_opr_opr, 0},
3761 {"modu.wl", 2, 0x38, mul_reg_opr_opr, 0},
3763 {"modu.pb", 2, 0x38, mul_reg_opr_opr, 0},
3764 {"modu.pw", 2, 0x38, mul_reg_opr_opr, 0},
3765 {"modu.pp", 2, 0x38, mul_reg_opr_opr, 0},
3766 {"modu.pl", 2, 0x38, mul_reg_opr_opr, 0},
3768 {"modu.lb", 2, 0x38, mul_reg_opr_opr, 0},
3769 {"modu.lw", 2, 0x38, mul_reg_opr_opr, 0},
3770 {"modu.lp", 2, 0x38, mul_reg_opr_opr, 0},
3771 {"modu.ll", 2, 0x38, mul_reg_opr_opr, 0}
3775 /* Gas line assembler entry point. */
3777 /* This is the main entry point for the machine-dependent assembler. str
3778 points to a machine-dependent instruction. This function is supposed to
3779 emit the frags/bytes it assembles to. */
3780 void
3781 md_assemble (char *str)
3783 char *op_start;
3784 char *op_end;
3785 char name[20];
3786 size_t nlen = 0;
3788 fail_line_pointer = NULL;
3790 /* Find the opcode end and get the opcode in 'name'. The opcode is forced
3791 lower case (the opcode table only has lower case op-codes). */
3792 for (op_start = op_end = str;
3793 *op_end && !is_end_of_line[(int)*op_end] && *op_end != ' ';
3794 op_end++)
3796 name[nlen] = TOLOWER (op_start[nlen]);
3797 nlen++;
3798 gas_assert (nlen < sizeof (name) - 1);
3800 name[nlen] = 0;
3802 if (nlen == 0)
3804 as_bad (_("No instruction or missing opcode."));
3805 return;
3808 input_line_pointer = skip_whites (op_end);
3810 size_t i;
3811 for (i = 0; i < sizeof (opcodes) / sizeof (opcodes[0]); ++i)
3813 const struct instruction *opc = opcodes + i;
3814 if (0 == strcmp (name, opc->name))
3816 if (opc->parse_operands (opc))
3817 return;
3818 continue;
3822 as_bad (_("Invalid instruction: \"%s\""), str);
3823 as_bad (_("First invalid token: \"%s\""), fail_line_pointer);
3824 while (*input_line_pointer++)
3832 /* Relocation, relaxation and frag conversions. */
3834 /* PC-relative offsets are relative to the start of the
3835 next instruction. That is, the address of the offset, plus its
3836 size, since the offset is always the last part of the insn. */
3837 long
3838 md_pcrel_from (fixS *fixP)
3840 long ret = fixP->fx_size + fixP->fx_frag->fr_address;
3841 if (fixP->fx_addsy && S_IS_DEFINED (fixP->fx_addsy))
3842 ret += fixP->fx_where;
3844 return ret;
3848 /* We need a port-specific relaxation function to cope with sym2 - sym1
3849 relative expressions with both symbols in the same segment (but not
3850 necessarily in the same frag as this insn), for example:
3851 ldab sym2-(sym1-2),pc
3852 sym1:
3853 The offset can be 5, 9 or 16 bits long. */
3855 long
3856 s12z_relax_frag (segT seg ATTRIBUTE_UNUSED, fragS *fragP ATTRIBUTE_UNUSED,
3857 long stretch ATTRIBUTE_UNUSED)
3859 return 0;
3862 void
3863 md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, asection *sec ATTRIBUTE_UNUSED,
3864 fragS *fragP ATTRIBUTE_UNUSED)
3868 /* On an ELF system, we can't relax a weak symbol. The weak symbol
3869 can be overridden at final link time by a non weak symbol. We can
3870 relax externally visible symbol because there is no shared library
3871 and such symbol can't be overridden (unless they are weak). */
3873 /* Force truly undefined symbols to their maximum size, and generally set up
3874 the frag list to be relaxed. */
3876 md_estimate_size_before_relax (fragS *fragP ATTRIBUTE_UNUSED, asection *segment ATTRIBUTE_UNUSED)
3878 return 0;
3882 /* If while processing a fixup, a reloc really needs to be created
3883 then it is done here. */
3884 arelent *
3885 tc_gen_reloc (asection *section, fixS *fixp)
3887 arelent *reloc = XNEW (arelent);
3888 reloc->sym_ptr_ptr = XNEW (asymbol *);
3889 *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
3890 reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
3891 reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type);
3892 if (reloc->howto == (reloc_howto_type *) NULL)
3894 as_bad_where (fixp->fx_file, fixp->fx_line,
3895 _("Relocation %d is not supported by object file format."),
3896 (int) fixp->fx_r_type);
3897 return NULL;
3900 if (0 == (section->flags & SEC_CODE))
3901 reloc->addend = fixp->fx_offset;
3902 else
3903 reloc->addend = fixp->fx_addnumber;
3905 return reloc;
3908 /* See whether we need to force a relocation into the output file. */
3910 tc_s12z_force_relocation (fixS *fixP)
3912 return generic_force_reloc (fixP);
3915 /* Here we decide which fixups can be adjusted to make them relative
3916 to the beginning of the section instead of the symbol. Basically
3917 we need to make sure that the linker relaxation is done
3918 correctly, so in some cases we force the original symbol to be
3919 used. */
3920 bool
3921 tc_s12z_fix_adjustable (fixS *fixP ATTRIBUTE_UNUSED)
3923 return true;
3926 void
3927 md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
3929 long value = *valP;
3931 if (fixP->fx_addsy == (symbolS *) NULL)
3932 fixP->fx_done = 1;
3934 /* We don't actually support subtracting a symbol. */
3935 if (fixP->fx_subsy != (symbolS *) NULL)
3936 as_bad_subtract (fixP);
3939 Patch the instruction with the resolved operand. Elf relocation
3940 info will also be generated to take care of linker/loader fixups.
3942 char *where = fixP->fx_frag->fr_literal + fixP->fx_where;
3944 switch (fixP->fx_r_type)
3946 case BFD_RELOC_8:
3947 ((bfd_byte *) where)[0] = (bfd_byte) value;
3948 break;
3949 case BFD_RELOC_16:
3950 bfd_putb16 ((bfd_vma) value, (unsigned char *) where);
3951 break;
3952 case BFD_RELOC_24:
3953 bfd_putb24 ((bfd_vma) value, (unsigned char *) where);
3954 break;
3955 case BFD_RELOC_S12Z_OPR:
3957 switch (fixP->fx_size)
3959 case 3:
3960 bfd_putb24 ((bfd_vma) value, (unsigned char *) where);
3961 break;
3962 case 2:
3963 bfd_putb16 ((bfd_vma) value, (unsigned char *) where);
3964 break;
3965 default:
3966 abort ();
3969 break;
3970 case BFD_RELOC_32:
3971 bfd_putb32 ((bfd_vma) value, (unsigned char *) where);
3972 break;
3973 case BFD_RELOC_16_PCREL:
3974 if (value < -0x4000 || value > 0x3FFF)
3975 as_bad_where (fixP->fx_file, fixP->fx_line,
3976 _("Value out of 16-bit range."));
3978 bfd_putb16 ((bfd_vma) value | 0x8000, (unsigned char *) where);
3979 break;
3981 default:
3982 as_fatal (_("Line %d: unknown relocation type: 0x%x."),
3983 fixP->fx_line, fixP->fx_r_type);
3987 /* Set the ELF specific flags. */
3988 void
3989 s12z_elf_final_processing (void)