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)
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. */
22 #include "safe-ctype.h"
24 #include "dwarf2dbg.h"
25 #include "opcode/s12z.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. */
44 s12z_strtol (const char *str
, char ** endptr
)
47 bool negative
= false;
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. */
61 else if (str
[0] == '+')
66 if (literal_prefix_dollar_hex
&& (str
[0] == '$'))
72 result
= strtol (str
, endptr
, base
);
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
[] =
117 /* Get the target cpu for the assembler. */
119 s12z_arch_format (void)
124 enum bfd_architecture
127 return bfd_arch_s12z
;
136 /* Listing header selected according to cpu. */
138 s12z_listing_header (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
);
152 s12z_print_statistics (FILE *file ATTRIBUTE_UNUSED
)
157 md_parse_option (int c
, const char *arg
)
161 case OPTION_REG_PREFIX
:
162 register_prefix
= xstrdup (arg
);
164 case OPTION_DOLLAR_HEX
:
165 literal_prefix_dollar_hex
= true;
174 md_undefined_symbol (char *name ATTRIBUTE_UNUSED
)
180 md_atof (int type
, char *litP
, int *sizeP
)
182 return ieee_md_atof (type
, litP
, sizeP
, true);
186 md_section_align (asection
*seg
, valueT addr
)
188 int align
= bfd_section_alignment (seg
);
189 return ((addr
+ (1 << align
) - 1) & -(1 << align
));
198 s12z_init_after_args (void)
200 if (flag_traditional_format
)
201 literal_prefix_dollar_hex
= true;
208 skip_whites (char *p
)
210 while (*p
== ' ' || *p
== '\t')
218 /* Start a new insn that contains at least 'size' bytes. Record the
219 line information of that insn in the dwarf2 debug sections. */
221 s12z_new_insn (int size
)
223 char *f
= frag_more (size
);
225 dwarf2_emit_insn (size
);
232 static bool lex_reg_name (uint16_t which
, int *reg
);
235 lex_constant (long *v
)
238 char *p
= input_line_pointer
;
240 /* A constant may not have the same value as a register
243 if (lex_reg_name (~0, &dummy
))
245 input_line_pointer
= p
;
250 *v
= s12z_strtol (p
, &end
);
251 if (errno
== 0 && end
!= p
)
253 input_line_pointer
= end
;
263 char *p
= input_line_pointer
;
267 input_line_pointer
++;
273 lex_expression (expressionS
*exp
)
275 char *ilp
= input_line_pointer
;
277 exp
->X_op
= O_absent
;
282 if (lex_reg_name (~0, &dummy
))
286 if (exp
->X_op
!= O_absent
)
290 fail_line_pointer
= input_line_pointer
;
291 input_line_pointer
= ilp
;
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.
300 lex_imm (long *v
, expressionS
*exp_o
)
302 char *ilp
= input_line_pointer
;
304 if (*input_line_pointer
!= '#')
307 input_line_pointer
++;
309 if (!lex_expression (&exp
))
312 if (exp
.X_op
!= O_constant
)
315 as_bad (_("A non-constant expression is not permitted here"));
320 *v
= exp
.X_add_number
;
324 fail_line_pointer
= input_line_pointer
;
325 input_line_pointer
= ilp
;
329 /* Short mmediate operand */
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))
341 fail_line_pointer
= input_line_pointer
;
342 input_line_pointer
= ilp
;
347 lex_match_string (const char *s
)
349 char *p
= input_line_pointer
;
350 while (p
!= 0 && *p
!= '\t' && *p
!= ' ' && *p
!= '\0')
355 size_t len
= p
- input_line_pointer
;
356 if (len
!= strlen (s
))
359 if (0 == strncasecmp (s
, input_line_pointer
, len
))
361 input_line_pointer
= p
;
368 /* Parse a register name.
369 WHICH is a ORwise combination of the registers which are accepted.
371 On success, REG will be filled with the index of the register which
372 was successfully scanned.
375 lex_reg_name (uint16_t which
, int *reg
)
377 char *p
= input_line_pointer
;
382 /* Scan (and ignore) the register prefix. */
385 int len
= strlen (register_prefix
);
386 if (0 == strncmp (register_prefix
, p
, len
))
392 char *start_of_reg_name
= p
;
394 while ((*p
>= 'a' && *p
<='z')
395 || (*p
>= '0' && *p
<= '9')
396 || (*p
>= 'A' && *p
<='Z'))
401 size_t len
= p
- start_of_reg_name
;
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
;
427 lex_force_match (char x
)
429 char *p
= input_line_pointer
;
432 as_bad (_("Expecting '%c'"), x
);
436 input_line_pointer
++;
441 lex_opr (uint8_t *buffer
, int *n_bytes
, expressionS
*exp
,
444 char *ilp
= input_line_pointer
;
445 uint8_t *xb
= buffer
;
448 exp
->X_op
= O_absent
;
451 if (lex_imm_e4 (&imm
))
455 as_bad (_("An immediate value in a source operand is inappropriate"));
466 else if (lex_reg_name (REG_BIT_Dn
, ®
))
473 else if (lex_match ('['))
475 if (lex_expression (exp
))
477 long c
= exp
->X_add_number
;
480 if (lex_reg_name (REG_BIT_XYSP
, ®
))
483 if (c
<= 255 && c
>= -256)
493 *xb
|= (reg
- REG_X
) << 4;
497 for (i
= 1; i
< *n_bytes
; ++i
)
499 buffer
[i
] = c
>> (8 * (*n_bytes
- i
- 1));
504 as_bad (_("Bad operand for constant offset"));
517 else if (lex_reg_name (REG_BIT_Dn
, ®
))
519 if (!lex_force_match (','))
523 if (lex_reg_name (REG_BIT_XY
, ®2
))
527 *xb
|= (reg2
- REG_X
) << 4;
532 as_bad (_("Invalid operand for register offset"));
540 if (!lex_force_match (']'))
544 else if (lex_match ('('))
547 if (lex_constant (&c
))
549 if (!lex_force_match (','))
552 if (lex_reg_name (REG_BIT_XYSP
, ®2
))
554 if (reg2
!= REG_P
&& c
>= 0 && c
<= 15)
558 *xb
|= (reg2
- REG_X
) << 4;
561 else if (c
>= -256 && c
<= 255)
565 *xb
|= (reg2
- REG_X
) << 4;
574 *xb
|= (reg2
- REG_X
) << 4;
580 else if (lex_reg_name (REG_BIT_Dn
, ®2
))
582 if (c
>= -1 * (long) (0x1u
<< 17)
584 c
< (long) (0x1u
<< 17) - 1)
589 *xb
|= ((c
>> 16) & 0x03) << 4;
605 as_bad (_("Bad operand for constant offset"));
609 else if (lex_reg_name (REG_BIT_Dn
, ®
))
614 if (lex_reg_name (REG_BIT_XYS
, ®2
))
618 *xb
|= (reg2
- REG_X
) << 4;
623 as_bad (_("Invalid operand for register offset"));
632 else if (lex_reg_name (REG_BIT_XYS
, ®
))
638 as_bad (_("Invalid register for postdecrement operation"));
644 else if (reg
== REG_Y
)
647 else if (lex_match ('+'))
652 else if (reg
== REG_Y
)
654 else if (reg
== REG_S
)
662 else if (lex_match ('+'))
664 if (lex_reg_name (REG_BIT_XY
, ®
))
669 else if (reg
== REG_Y
)
674 as_bad (_("Invalid register for preincrement operation"));
678 else if (lex_match ('-'))
680 if (lex_reg_name (REG_BIT_XYS
, ®
))
685 else if (reg
== REG_Y
)
687 else if (reg
== REG_S
)
692 as_bad (_("Invalid register for predecrement operation"));
701 if (! lex_match (')'))
705 else if (lex_expression (exp
))
712 if (exp
->X_op
== O_constant
)
714 valueT value
= exp
->X_add_number
;
716 if (value
< (0x1U
<< 14))
723 else if (value
< (0x1U
<< 19))
726 if (value
& (0x1U
<< 17))
728 if (value
& (0x1U
<< 16))
731 buffer
[1] = value
>> 8;
738 buffer
[1] = value
>> 16;
739 buffer
[2] = value
>> 8;
747 fail_line_pointer
= input_line_pointer
;
748 input_line_pointer
= ilp
;
753 lex_offset (long *val
)
756 char *p
= input_line_pointer
;
761 if (*p
!= '+' && *p
!= '-')
764 bool negative
= (*p
== '-');
768 *val
= s12z_strtol (p
, &end
);
773 input_line_pointer
= end
;
784 typedef bool (*parse_operand_func
) (const struct instruction
*);
790 /* The "page" to which the instruction belongs.
791 This is also only a hint. Some instructions might have modes in both
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.
800 parse_operand_func parse_operands
;
802 /* Some instructions can be encoded with a different opcode */
807 no_operands (const struct instruction
*insn
)
809 if (*input_line_pointer
!= '\0')
811 as_bad (_("Garbage at end of instruction"));
815 char *f
= s12z_new_insn (insn
->page
);
817 number_to_chars_bigendian (f
++, PAGE2_PREBYTE
, 1);
819 number_to_chars_bigendian (f
++, insn
->opc
, 1);
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
,
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 */
846 emit_opr (char *f
, const uint8_t *buffer
, int n_bytes
, expressionS
*exp
)
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);
859 /* Emit the code for a 24 bit direct address operand */
861 emit_ext24 (char *f
, long v
)
863 number_to_chars_bigendian (f
, v
, 3);
869 opr (const struct instruction
*insn
)
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
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
);
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
);
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.
908 lex_15_bit_offset (bool *long_displacement
, expressionS
*exp
)
910 char *ilp
= input_line_pointer
;
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
;
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;
934 exp
->X_op
= O_absent
;
938 if (val
> 0x3FFF || val
< -0x4000)
940 as_fatal (_("Offset is outside of 15 bit range"));
944 *long_displacement
= (val
> 63 || val
< -64);
949 fail_line_pointer
= input_line_pointer
;
950 input_line_pointer
= ilp
;
955 emit_15_bit_offset (char *f
, int where
, expressionS
*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
,
967 fix
->fx_addnumber
= where
- 2;
971 long val
= exp
->X_add_number
;
972 bool long_displacement
= (val
> 63 || val
< -64);
973 if (long_displacement
)
978 number_to_chars_bigendian (f
++, val
, long_displacement
? 2 : 1);
983 rel (const struct instruction
*insn
)
985 bool long_displacement
;
988 if (! lex_15_bit_offset (&long_displacement
, &exp
))
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
);
998 reg_inh (const struct instruction
*insn
)
1001 if (lex_reg_name (REG_BIT_Dn
, ®
))
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);
1015 /* Special case for CLR X and CLR Y */
1017 clr_xy (const struct instruction
*insn ATTRIBUTE_UNUSED
)
1020 if (lex_reg_name (REG_BIT_XY
, ®
))
1022 char *f
= s12z_new_insn (1);
1023 number_to_chars_bigendian (f
, 0x9a + reg
- REG_X
, 1);
1030 /* Some instructions have a suffix like ".l", ".b", ".w" etc
1031 which indicates the size of the operands. */
1033 size_from_suffix (const struct instruction
*insn
, int idx
)
1035 const char *dot
= strchr (insn
->name
, '.');
1041 switch (dot
[1 + idx
])
1056 as_fatal (_("Bad size"));
1063 mul_reg_reg_reg (const struct instruction
*insn
)
1065 char *ilp
= input_line_pointer
;
1068 if (!lex_reg_name (REG_BIT_Dn
, &Dd
))
1071 if (!lex_match (','))
1075 if (!lex_reg_name (REG_BIT_Dn
, &Dj
))
1078 if (!lex_match (','))
1082 if (!lex_reg_name (REG_BIT_Dn
, &Dk
))
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
, '.');
1101 as_fatal (_("BAD MUL"));
1108 number_to_chars_bigendian (f
++, mb
, 1);
1113 fail_line_pointer
= input_line_pointer
;
1114 input_line_pointer
= ilp
;
1120 mul_reg_reg_imm (const struct instruction
*insn
)
1122 char *ilp
= input_line_pointer
;
1125 if (!lex_reg_name (REG_BIT_Dn
, &Dd
))
1128 if (!lex_match (','))
1132 if (!lex_reg_name (REG_BIT_Dn
, &Dj
))
1135 if (!lex_match (','))
1139 if (!lex_imm (&imm
, NULL
))
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);
1151 const char *dot
= strchrnul (insn
->name
, '.');
1161 as_fatal (_("BAD MUL"));
1168 number_to_chars_bigendian (f
++, mb
, 1);
1169 number_to_chars_bigendian (f
++, imm
, size
);
1174 fail_line_pointer
= input_line_pointer
;
1175 input_line_pointer
= ilp
;
1181 mul_reg_reg_opr (const struct instruction
*insn
)
1183 char *ilp
= input_line_pointer
;
1186 if (!lex_reg_name (REG_BIT_Dn
, &Dd
))
1189 if (!lex_match (','))
1193 if (!lex_reg_name (REG_BIT_Dn
, &Dj
))
1196 if (!lex_match (','))
1202 if (!lex_opr (buffer
, &n_bytes
, &exp
, true))
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);
1213 const char *dot
= strchrnul (insn
->name
, '.');
1223 as_fatal (_("BAD MUL"));
1230 number_to_chars_bigendian (f
++, mb
, 1);
1232 emit_opr (f
, buffer
, n_bytes
, &exp
);
1237 fail_line_pointer
= input_line_pointer
;
1238 input_line_pointer
= ilp
;
1243 mul_reg_opr_opr (const struct instruction
*insn
)
1245 char *ilp
= input_line_pointer
;
1248 if (!lex_reg_name (REG_BIT_Dn
, &Dd
))
1251 if (!lex_match (','))
1257 if (!lex_opr (buffer1
, &n_bytes1
, &exp1
, false))
1260 if (!lex_match (','))
1266 if (!lex_opr (buffer2
, &n_bytes2
, &exp2
, false))
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);
1278 const char *dot
= strchrnul (insn
->name
, '.');
1288 as_fatal (_("BAD MUL"));
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
);
1302 fail_line_pointer
= input_line_pointer
;
1303 input_line_pointer
= ilp
;
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) | \
1316 #define REG_BIT_GRP1 \
1317 ((0x1U << REG_D4) | \
1318 (0x1U << REG_D5) | \
1319 (0x1U << REG_D6) | \
1320 (0x1U << REG_D7) | \
1324 static const uint8_t reg_map
[] =
1344 lex_reg_list (uint16_t grp
, uint16_t *reg_bits
)
1346 if (lex_match (','))
1349 if (!lex_reg_name (grp
, ®
))
1351 *reg_bits
|= 0x1u
<< reg
;
1352 lex_reg_list (grp
, reg_bits
);
1360 psh_pull (const struct instruction
*insn
)
1363 (0 == strcmp ("pul", insn
->name
)) ? 0x80: 0x00;
1365 if (lex_match_string ("all16b"))
1369 else if (lex_match_string ("all"))
1376 if (!lex_reg_name (REG_BIT_GRP1
| REG_BIT_GRP0
, ®1
))
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
, ®_bits
))
1389 if (reg_bits
& REG_BIT_GRP1
)
1393 for (i
= 0; i
< 16; ++i
)
1395 if (reg_bits
& (0x1u
<< 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);
1406 fail_line_pointer
= input_line_pointer
;
1412 tfr (const struct instruction
*insn
)
1415 if (!lex_reg_name (~0, ®1
))
1418 if (!lex_match (','))
1422 if (!lex_reg_name (~0, ®2
))
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"),
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);
1443 fail_line_pointer
= input_line_pointer
;
1448 imm8 (const struct instruction
*insn
)
1451 if (! lex_imm (&imm
, NULL
))
1453 if (imm
> 127 || imm
< -128)
1455 as_bad (_("Immediate value %ld is out of range for instruction %s"),
1459 char *f
= s12z_new_insn (2);
1460 number_to_chars_bigendian (f
++, insn
->opc
, 1);
1461 number_to_chars_bigendian (f
++, imm
, 1);
1467 reg_imm (const struct instruction
*insn
, int allowed_reg
)
1469 char *ilp
= input_line_pointer
;
1471 if (lex_reg_name (allowed_reg
, ®
))
1473 if (!lex_force_match (','))
1476 if (! lex_imm (&imm
, NULL
))
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
);
1490 fail_line_pointer
= input_line_pointer
;
1491 input_line_pointer
= ilp
;
1497 regd_imm (const struct instruction
*insn
)
1499 return reg_imm (insn
, REG_BIT_Dn
);
1503 regdxy_imm (const struct instruction
*insn
)
1505 return reg_imm (insn
, REG_BIT_Dn
| REG_BIT_XY
);
1510 regs_imm (const struct instruction
*insn
)
1512 return reg_imm (insn
, 0x1U
<< REG_S
);
1516 trap_imm (const struct instruction
*insn ATTRIBUTE_UNUSED
)
1519 if (! lex_imm (&imm
, NULL
))
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
);
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);
1540 fail_line_pointer
= input_line_pointer
;
1546 /* Special one byte instruction CMP X, Y */
1548 regx_regy (const struct instruction
*insn
)
1551 if (lex_reg_name (0x1U
<< REG_X
, ®
))
1553 if (lex_force_match (','))
1555 if (lex_reg_name (0x1U
<< REG_Y
, ®
))
1557 char *f
= s12z_new_insn (1);
1558 number_to_chars_bigendian (f
, insn
->opc
, 1);
1566 /* Special one byte instruction SUB D6, X, Y */
1568 regd6_regx_regy (const struct instruction
*insn
)
1570 char *ilp
= input_line_pointer
;
1572 if (!lex_reg_name (0x1U
<< REG_D6
, ®
))
1575 if (!lex_match (','))
1578 if (!lex_reg_name (0x1U
<< REG_X
, ®
))
1581 if (!lex_match (','))
1584 if (!lex_reg_name (0x1U
<< REG_Y
, ®
))
1587 char *f
= s12z_new_insn (1);
1588 number_to_chars_bigendian (f
, insn
->opc
, 1);
1592 fail_line_pointer
= input_line_pointer
;
1593 input_line_pointer
= ilp
;
1597 /* Special one byte instruction SUB D6, Y, X */
1599 regd6_regy_regx (const struct instruction
*insn
)
1601 char *ilp
= input_line_pointer
;
1603 if (!lex_reg_name (0x1U
<< REG_D6
, ®
))
1606 if (!lex_match (','))
1609 if (!lex_reg_name (0x1U
<< REG_Y
, ®
))
1612 if (!lex_match (','))
1615 if (!lex_reg_name (0x1U
<< REG_X
, ®
))
1618 char *f
= s12z_new_insn (1);
1619 number_to_chars_bigendian (f
, insn
->opc
, 1);
1623 fail_line_pointer
= input_line_pointer
;
1624 input_line_pointer
= ilp
;
1629 reg_opr (const struct instruction
*insn
, int allowed_regs
,
1632 char *ilp
= input_line_pointer
;
1634 if (lex_reg_name (allowed_regs
, ®
))
1636 if (!lex_force_match (','))
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
);
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
);
1676 fail_line_pointer
= input_line_pointer
;
1677 input_line_pointer
= ilp
;
1683 regdxy_opr_dest (const struct instruction
*insn
)
1685 return reg_opr (insn
, REG_BIT_Dn
| REG_BIT_XY
, false);
1689 regdxy_opr_src (const struct instruction
*insn
)
1691 return reg_opr (insn
, REG_BIT_Dn
| REG_BIT_XY
, true);
1696 regd_opr (const struct instruction
*insn
)
1698 return reg_opr (insn
, REG_BIT_Dn
, true);
1702 /* OP0: S; OP1: destination OPR */
1704 regs_opr_dest (const struct instruction
*insn
)
1706 return reg_opr (insn
, 0x1U
<< REG_S
, false);
1709 /* OP0: S; OP1: source OPR */
1711 regs_opr_src (const struct instruction
*insn
)
1713 return reg_opr (insn
, 0x1U
<< REG_S
, true);
1717 imm_opr (const struct instruction
*insn
)
1719 char *ilp
= input_line_pointer
;
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
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
))
1736 if (!lex_match (','))
1742 if (!lex_opr (buffer
, &n_bytes
, &exp1
, false))
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
);
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
);
1759 fail_line_pointer
= input_line_pointer
;
1760 input_line_pointer
= ilp
;
1765 opr_opr (const struct instruction
*insn
)
1767 char *ilp
= input_line_pointer
;
1772 if (!lex_opr (buffer1
, &n_bytes1
, &exp1
, false))
1776 if (!lex_match (','))
1782 if (!lex_opr (buffer2
, &n_bytes2
, &exp2
, false))
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
);
1794 fail_line_pointer
= input_line_pointer
;
1795 input_line_pointer
= ilp
;
1800 reg67sxy_opr (const struct instruction
*insn
)
1803 if (!lex_reg_name (REG_BIT_XYS
| (0x1U
<< REG_D6
) | (0x1U
<< REG_D7
), ®
))
1806 if (!lex_match (','))
1812 if (!lex_opr (buffer
, &n_bytes
, &exp
, 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
);
1823 rotate (const struct instruction
*insn
, short dir
)
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);
1839 number_to_chars_bigendian (f
++, sb
, 1);
1840 emit_opr (f
, buffer
, n_bytes
, &exp
);
1849 rol (const struct instruction
*insn
)
1851 return rotate (insn
, 1);
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;
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
1872 Then, it rewinds the input and parses it again as a OPR.
1874 char *ilp
= input_line_pointer
;
1877 if (!lex_reg_name (REG_BIT_Dn
, &Dd
))
1882 if (!lex_match (','))
1886 if (!lex_imm (&imm
, NULL
))
1889 if (imm
!= 1 && imm
!= 2)
1891 input_line_pointer
= ilp
;
1893 /* Now parse the first operand again */
1899 if (!lex_opr (buffer
, &n_bytes
, &exp
, false))
1902 gas_assert (n_bytes
== 1);
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
);
1918 fail_line_pointer
= input_line_pointer
;
1919 input_line_pointer
= ilp
;
1923 /* Shift instruction with a register operand.
1924 left = 1; right = 0;
1925 logical = 0; arithmetic = 1; */
1927 lex_shift_reg (const struct instruction
*insn
, short type
, short dir
)
1930 if (!lex_reg_name (REG_BIT_Dn
, &Dd
))
1935 if (!lex_match (','))
1938 if (!lex_reg_name (REG_BIT_Dn
, &Ds
))
1943 if (!lex_match (','))
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);
1958 number_to_chars_bigendian (f
++, xb
, 1);
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]"));
1971 if (imm
== 1 || imm
== 2)
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);
1988 number_to_chars_bigendian (f
++, xb
, 1);
1995 fail_line_pointer
= input_line_pointer
;
2000 impute_shift_dir_and_type (const struct instruction
*insn
, short *type
, short *dir
)
2004 switch (insn
->name
[0])
2013 as_fatal (_("Bad shift mode"));
2017 switch (insn
->name
[2])
2026 as_fatal (_("Bad shift *direction"));
2031 /* Shift instruction with a OPR operand */
2033 shift_two_operand (const struct instruction
*insn
)
2036 char *ilp
= input_line_pointer
;
2040 impute_shift_dir_and_type (insn
, &type
, &dir
);
2044 int size
= size_from_suffix (insn
, 0);
2050 if (!lex_opr (buffer
, &n_opr_bytes
, &exp
, false))
2053 if (!lex_match (','))
2057 if (!lex_imm (&imm
, NULL
))
2060 if (imm
!= 1 && imm
!= 2)
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
);
2074 fail_line_pointer
= input_line_pointer
;
2075 input_line_pointer
= ilp
;
2079 /* Shift instruction with a OPR operand */
2081 shift_opr_imm (const struct instruction
*insn
)
2083 char *ilp
= input_line_pointer
;
2087 impute_shift_dir_and_type (insn
, &type
, &dir
);
2090 if (!lex_reg_name (REG_BIT_Dn
, &Dd
))
2093 if (!lex_match (','))
2102 if (!lex_opr (buffer1
, &n_opr_bytes1
, &exp1
, false))
2105 n_bytes
+= n_opr_bytes1
;
2106 if (!lex_match (','))
2110 int n_opr_bytes2
= 0;
2113 bool immediate
= false;
2114 if (lex_imm (&imm
, NULL
))
2118 else if (!lex_opr (buffer2
, &n_opr_bytes2
, &exp2
, false))
2123 int size
= size_from_suffix (insn
, 0);
2133 if (imm
== 2 || imm
== 1)
2148 n_bytes
+= n_opr_bytes2
;
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
);
2158 if (imm
!= 1 && imm
!= 2)
2160 number_to_chars_bigendian (f
++, 0x70 | (imm
>> 1), 1);
2165 f
= emit_opr (f
, buffer2
, n_opr_bytes2
, &exp2
);
2171 fail_line_pointer
= input_line_pointer
;
2172 input_line_pointer
= ilp
;
2176 /* Shift instruction with a register operand */
2178 shift_reg (const struct instruction
*insn
)
2182 impute_shift_dir_and_type (insn
, &type
, &dir
);
2184 if (lex_shift_reg_imm1 (insn
, type
, dir
))
2187 return lex_shift_reg (insn
, type
, dir
);
2191 bm_regd_imm (const struct instruction
*insn
)
2193 char *ilp
= input_line_pointer
;
2195 if (!lex_reg_name (REG_BIT_Dn
, &Di
))
2198 if (!lex_match (','))
2202 if (!lex_imm (&imm
, NULL
))
2206 uint8_t bm
= imm
<< 3;
2209 char *f
= s12z_new_insn (2);
2210 number_to_chars_bigendian (f
++, insn
->opc
, 1);
2211 number_to_chars_bigendian (f
++, bm
, 1);
2216 fail_line_pointer
= input_line_pointer
;
2217 input_line_pointer
= ilp
;
2222 bm_opr_reg (const struct instruction
*insn
)
2224 char *ilp
= input_line_pointer
;
2230 if (!lex_opr (buffer
, &n_opr_bytes
, &exp
, false))
2233 if (!lex_match (','))
2237 if (!lex_reg_name (REG_BIT_Dn
, &Dn
))
2240 uint8_t bm
= Dn
<< 4;
2241 int size
= size_from_suffix (insn
, 0);
2242 bm
|= (size
- 1) << 2;
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
);
2254 fail_line_pointer
= input_line_pointer
;
2255 input_line_pointer
= ilp
;
2261 bm_opr_imm (const struct instruction
*insn
)
2263 char *ilp
= input_line_pointer
;
2269 if (!lex_opr (buffer
, &n_opr_bytes
, &exp
, false))
2272 if (!lex_match (','))
2277 if (!lex_imm (&imm
, NULL
))
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
);
2293 bm
|= (imm
& 0x07) << 4;
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
);
2305 fail_line_pointer
= input_line_pointer
;
2306 input_line_pointer
= ilp
;
2312 bm_regd_reg (const struct instruction
*insn
)
2314 char *ilp
= input_line_pointer
;
2316 if (!lex_reg_name (REG_BIT_Dn
, &Di
))
2319 if (!lex_match (','))
2323 if (!lex_reg_name (REG_BIT_Dn
, &Dn
))
2326 uint8_t bm
= Dn
<< 4;
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);
2339 fail_line_pointer
= input_line_pointer
;
2340 input_line_pointer
= ilp
;
2349 bf_reg_opr_imm (const struct instruction
*insn
, short ie
)
2351 char *ilp
= input_line_pointer
;
2353 if (!lex_reg_name (REG_BIT_Dn
, &Dd
))
2356 if (!lex_match (','))
2363 if (!lex_opr (buffer
, &n_bytes
, &exp
, false))
2366 if (!lex_match (','))
2370 if (!lex_imm (&width
, NULL
))
2373 if (width
< 0 || width
> 31)
2375 as_bad (_("Invalid width value for %s"), insn
->name
);
2379 if (!lex_match (':'))
2383 if (!lex_constant (&offset
))
2386 if (offset
< 0 || offset
> 31)
2388 as_bad (_("Invalid offset value for %s"), insn
->name
);
2392 uint8_t i1
= width
<< 5;
2395 int size
= size_from_suffix (insn
, 0);
2396 uint8_t bb
= ie
? 0x80 : 0x00;
2398 bb
|= (size
- 1) << 2;
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
);
2412 fail_line_pointer
= input_line_pointer
;
2413 input_line_pointer
= ilp
;
2419 bf_opr_reg_imm (const struct instruction
*insn
, short ie
)
2421 char *ilp
= input_line_pointer
;
2425 if (!lex_opr (buffer
, &n_bytes
, &exp
, false))
2428 if (!lex_match (','))
2432 if (!lex_reg_name (REG_BIT_Dn
, &Ds
))
2435 if (!lex_match (','))
2439 if (!lex_imm (&width
, NULL
))
2442 if (width
< 0 || width
> 31)
2444 as_bad (_("Invalid width value for %s"), insn
->name
);
2448 if (!lex_match (':'))
2452 if (!lex_constant (&offset
))
2455 if (offset
< 0 || offset
> 31)
2457 as_bad (_("Invalid offset value for %s"), insn
->name
);
2461 uint8_t i1
= width
<< 5;
2464 int size
= size_from_suffix (insn
, 0);
2465 uint8_t bb
= ie
? 0x80 : 0x00;
2467 bb
|= (size
- 1) << 2;
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
);
2481 fail_line_pointer
= input_line_pointer
;
2482 input_line_pointer
= ilp
;
2489 bf_reg_reg_imm (const struct instruction
*insn
, short ie
)
2491 char *ilp
= input_line_pointer
;
2493 if (!lex_reg_name (REG_BIT_Dn
, &Dd
))
2496 if (!lex_match (','))
2500 if (!lex_reg_name (REG_BIT_Dn
, &Ds
))
2503 if (!lex_match (','))
2507 if (!lex_imm (&width
, NULL
))
2510 if (width
< 0 || width
> 31)
2512 as_bad (_("Invalid width value for %s"), insn
->name
);
2516 if (!lex_match (':'))
2520 if (!lex_constant (&offset
))
2523 if (offset
< 0 || offset
> 31)
2525 as_bad (_("Invalid offset value for %s"), insn
->name
);
2529 uint8_t bb
= ie
? 0x80 : 0x00;
2534 uint8_t i1
= width
<< 5;
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);
2546 fail_line_pointer
= input_line_pointer
;
2547 input_line_pointer
= ilp
;
2552 bf_reg_reg_reg (const struct instruction
*insn ATTRIBUTE_UNUSED
, short ie
)
2554 char *ilp
= input_line_pointer
;
2556 if (!lex_reg_name (REG_BIT_Dn
, &Dd
))
2559 if (!lex_match (','))
2563 if (!lex_reg_name (REG_BIT_Dn
, &Ds
))
2566 if (!lex_match (','))
2570 if (!lex_reg_name ((0x01u
<< REG_D2
) |
2577 uint8_t bb
= ie
? 0x80 : 0x00;
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);
2589 fail_line_pointer
= input_line_pointer
;
2590 input_line_pointer
= ilp
;
2595 bf_opr_reg_reg (const struct instruction
*insn
, short ie
)
2597 char *ilp
= input_line_pointer
;
2602 if (!lex_opr (buffer
, &n_bytes
, &exp
, false))
2605 if (!lex_match (','))
2610 if (!lex_reg_name (REG_BIT_Dn
, &Ds
))
2613 if (!lex_match (','))
2618 if (!lex_reg_name ((0x01u
<< REG_D2
) |
2625 int size
= size_from_suffix (insn
, 0);
2626 uint8_t bb
= ie
? 0x80 : 0x00;
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
);
2641 fail_line_pointer
= input_line_pointer
;
2642 input_line_pointer
= ilp
;
2648 bf_reg_opr_reg (const struct instruction
*insn
, short ie
)
2650 char *ilp
= input_line_pointer
;
2652 if (!lex_reg_name (REG_BIT_Dn
, &Dd
))
2655 if (!lex_match (','))
2662 if (!lex_opr (buffer
, &n_bytes
, &exp
, false))
2665 if (!lex_match (','))
2669 if (!lex_reg_name ((0x01u
<< REG_D2
) |
2676 int size
= size_from_suffix (insn
, 0);
2677 uint8_t bb
= ie
? 0x80 : 0x00;
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
);
2692 fail_line_pointer
= input_line_pointer
;
2693 input_line_pointer
= ilp
;
2700 bfe_reg_reg_reg (const struct instruction
*insn
)
2702 return bf_reg_reg_reg (insn
, 0);
2706 bfi_reg_reg_reg (const struct instruction
*insn
)
2708 return bf_reg_reg_reg (insn
, 1);
2712 bfe_reg_reg_imm (const struct instruction
*insn
)
2714 return bf_reg_reg_imm (insn
, 0);
2718 bfi_reg_reg_imm (const struct instruction
*insn
)
2720 return bf_reg_reg_imm (insn
, 1);
2725 bfe_reg_opr_reg (const struct instruction
*insn
)
2727 return bf_reg_opr_reg (insn
, 0);
2731 bfi_reg_opr_reg (const struct instruction
*insn
)
2733 return bf_reg_opr_reg (insn
, 1);
2738 bfe_opr_reg_reg (const struct instruction
*insn
)
2740 return bf_opr_reg_reg (insn
, 0);
2744 bfi_opr_reg_reg (const struct instruction
*insn
)
2746 return bf_opr_reg_reg (insn
, 1);
2750 bfe_reg_opr_imm (const struct instruction
*insn
)
2752 return bf_reg_opr_imm (insn
, 0);
2756 bfi_reg_opr_imm (const struct instruction
*insn
)
2758 return bf_reg_opr_imm (insn
, 1);
2762 bfe_opr_reg_imm (const struct instruction
*insn
)
2764 return bf_opr_reg_imm (insn
, 0);
2768 bfi_opr_reg_imm (const struct instruction
*insn
)
2770 return bf_opr_reg_imm (insn
, 1);
2777 tb_reg_rel (const struct instruction
*insn
)
2779 char *ilp
= input_line_pointer
;
2782 if (!lex_reg_name (REG_BIT_Dn
| REG_BIT_XY
, ®
))
2785 if (!lex_match (','))
2788 bool long_displacement
;
2790 if (! lex_15_bit_offset (&long_displacement
, &exp
))
2794 if (reg
== REG_X
|| reg
== REG_Y
)
2805 if (startswith (insn
->name
+ 2, "ne"))
2807 else if (startswith (insn
->name
+ 2, "eq"))
2809 else if (startswith (insn
->name
+ 2, "pl"))
2811 else if (startswith (insn
->name
+ 2, "mi"))
2813 else if (startswith (insn
->name
+ 2, "gt"))
2815 else if (startswith (insn
->name
+ 2, "le"))
2818 switch (insn
->name
[0])
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
);
2839 fail_line_pointer
= input_line_pointer
;
2840 input_line_pointer
= ilp
;
2846 tb_opr_rel (const struct instruction
*insn
)
2848 char *ilp
= input_line_pointer
;
2853 if (!lex_opr (buffer
, &n_bytes
, &exp
, false))
2856 if (!lex_match (','))
2859 bool long_displacement
;
2861 if (! lex_15_bit_offset (&long_displacement
, &exp2
))
2866 if (startswith (insn
->name
+ 2, "ne"))
2868 else if (startswith (insn
->name
+ 2, "eq"))
2870 else if (startswith (insn
->name
+ 2, "pl"))
2872 else if (startswith (insn
->name
+ 2, "mi"))
2874 else if (startswith (insn
->name
+ 2, "gt"))
2876 else if (startswith (insn
->name
+ 2, "le"))
2879 switch (insn
->name
[0])
2891 int size
= size_from_suffix (insn
, 0);
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
);
2905 fail_line_pointer
= input_line_pointer
;
2906 input_line_pointer
= ilp
;
2914 test_br_reg_reg_rel (const struct instruction
*insn
)
2916 char *ilp
= input_line_pointer
;
2919 if (!lex_reg_name (REG_BIT_Dn
, &Di
))
2922 if (!lex_match (','))
2927 if (!lex_reg_name (REG_BIT_Dn
, &Dn
))
2930 if (!lex_match (','))
2934 bool long_displacement
;
2936 if (! lex_15_bit_offset (&long_displacement
, &exp
))
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
);
2955 fail_line_pointer
= input_line_pointer
;
2956 input_line_pointer
= ilp
;
2961 test_br_opr_reg_rel (const struct instruction
*insn
)
2963 char *ilp
= input_line_pointer
;
2968 if (!lex_opr (buffer
, &n_bytes
, &exp
, false))
2971 if (!lex_match (','))
2975 if (!lex_reg_name (REG_BIT_Dn
, &Dn
))
2978 if (!lex_match (','))
2983 int size
= size_from_suffix (insn
, 0);
2984 bm
|= (size
-1) << 2;
2986 bool long_displacement
;
2989 if (! lex_15_bit_offset (&long_displacement
, &exp2
))
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
);
3003 fail_line_pointer
= input_line_pointer
;
3004 input_line_pointer
= ilp
;
3010 test_br_opr_imm_rel (const struct instruction
*insn
)
3012 char *ilp
= input_line_pointer
;
3017 if (!lex_opr (buffer
, &n_bytes
, &exp
, false))
3020 if (!lex_match (','))
3024 if (!lex_imm (&imm
, NULL
))
3027 if (imm
< 0 || imm
> 31)
3030 if (!lex_match (','))
3033 bool long_displacement
;
3035 if (! lex_15_bit_offset (&long_displacement
, &exp2
))
3038 int size
= size_from_suffix (insn
, 0);
3041 bm
|= (imm
& 0x07) << 4;
3042 bm
|= (imm
>> 3) & 0x03;
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
);
3058 fail_line_pointer
= input_line_pointer
;
3059 input_line_pointer
= ilp
;
3065 test_br_reg_imm_rel (const struct instruction
*insn
)
3067 char *ilp
= input_line_pointer
;
3070 if (!lex_reg_name (REG_BIT_Dn
, &Di
))
3073 if (!lex_match (','))
3077 if (!lex_imm (&imm
, NULL
))
3080 if (imm
< 0 || imm
> 31)
3084 if (!lex_match (','))
3087 bool long_displacement
;
3089 if (! lex_15_bit_offset (&long_displacement
, &exp
))
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
);
3104 fail_line_pointer
= input_line_pointer
;
3105 input_line_pointer
= ilp
;
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},
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. */
3781 md_assemble (char *str
)
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
!= ' ';
3796 name
[nlen
] = TOLOWER (op_start
[nlen
]);
3798 gas_assert (nlen
< sizeof (name
) - 1);
3804 as_bad (_("No instruction or missing opcode."));
3808 input_line_pointer
= skip_whites (op_end
);
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
))
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. */
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
;
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
3853 The offset can be 5, 9 or 16 bits long. */
3856 s12z_relax_frag (segT seg ATTRIBUTE_UNUSED
, fragS
*fragP ATTRIBUTE_UNUSED
,
3857 long stretch ATTRIBUTE_UNUSED
)
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
)
3882 /* If while processing a fixup, a reloc really needs to be created
3883 then it is done here. */
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
);
3900 if (0 == (section
->flags
& SEC_CODE
))
3901 reloc
->addend
= fixp
->fx_offset
;
3903 reloc
->addend
= fixp
->fx_addnumber
;
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
3921 tc_s12z_fix_adjustable (fixS
*fixP ATTRIBUTE_UNUSED
)
3927 md_apply_fix (fixS
*fixP
, valueT
*valP
, segT seg ATTRIBUTE_UNUSED
)
3931 if (fixP
->fx_addsy
== (symbolS
*) NULL
)
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
)
3947 ((bfd_byte
*) where
)[0] = (bfd_byte
) value
;
3950 bfd_putb16 ((bfd_vma
) value
, (unsigned char *) where
);
3953 bfd_putb24 ((bfd_vma
) value
, (unsigned char *) where
);
3955 case BFD_RELOC_S12Z_OPR
:
3957 switch (fixP
->fx_size
)
3960 bfd_putb24 ((bfd_vma
) value
, (unsigned char *) where
);
3963 bfd_putb16 ((bfd_vma
) value
, (unsigned char *) where
);
3971 bfd_putb32 ((bfd_vma
) value
, (unsigned char *) where
);
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
);
3982 as_fatal (_("Line %d: unknown relocation type: 0x%x."),
3983 fixP
->fx_line
, fixP
->fx_r_type
);
3987 /* Set the ELF specific flags. */
3989 s12z_elf_final_processing (void)