1 /* tc-s12z.c -- Assembler code for the Freescale S12Z
2 Copyright (C) 2018-2020 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"
30 const char comment_chars
[] = ";";
32 const char line_comment_chars
[] = "#*";
33 const char line_separator_chars
[] = "";
35 static char * register_prefix
= NULL
;
37 const char EXP_CHARS
[] = "eE";
38 const char FLT_CHARS
[] = "dD";
40 static char *fail_line_pointer
;
42 /* A wrapper around the standard library's strtol.
43 It converts STR into an integral value.
44 This wrapper deals with literal_prefix_dollar_hex. */
46 s12z_strtol (const char *str
, char ** endptr
)
49 bool negative
= false;
53 char *start
= (char *) str
;
55 /* In the case where literal_prefix_dollar_hex is TRUE the sign has
56 to be handled explicitly. Otherwise the string will not be
57 recognised as an integer. */
63 else if (str
[0] == '+')
68 if (literal_prefix_dollar_hex
&& (str
[0] == '$'))
74 result
= strtol (str
, endptr
, base
);
87 /* Options and initialization. */
89 const char *md_shortopts
= "";
91 struct option md_longopts
[] =
93 #define OPTION_REG_PREFIX (OPTION_MD_BASE)
94 {"mreg-prefix", required_argument
, NULL
, OPTION_REG_PREFIX
},
95 #define OPTION_DOLLAR_HEX (OPTION_MD_BASE + 1)
96 {"mdollar-hex", no_argument
, NULL
, OPTION_DOLLAR_HEX
},
97 {NULL
, no_argument
, NULL
, 0}
100 size_t md_longopts_size
= sizeof (md_longopts
);
103 relax_typeS md_relax_table
[] =
108 /* This table describes all the machine specific pseudo-ops the assembler
109 has to support. The fields are:
110 pseudo-op name without dot
111 function to call to execute this pseudo-op
112 Integer arg to pass to the function. */
113 const pseudo_typeS md_pseudo_table
[] =
119 /* Get the target cpu for the assembler. */
121 s12z_arch_format (void)
126 enum bfd_architecture
129 return bfd_arch_s12z
;
138 /* Listing header selected according to cpu. */
140 s12z_listing_header (void)
146 md_show_usage (FILE *stream
)
148 fputs (_("\ns12z options:\n"), stream
);
149 fputs (_(" -mreg-prefix=PREFIX set a prefix used to indicate register names (default none)\n"), stream
);
150 fputs (_(" -mdollar-hex the prefix '$' instead of '0x' is used to indicate literal hexadecimal constants\n"), stream
);
154 s12z_print_statistics (FILE *file ATTRIBUTE_UNUSED
)
159 md_parse_option (int c
, const char *arg
)
163 case OPTION_REG_PREFIX
:
164 register_prefix
= xstrdup (arg
);
166 case OPTION_DOLLAR_HEX
:
167 literal_prefix_dollar_hex
= TRUE
;
176 md_undefined_symbol (char *name ATTRIBUTE_UNUSED
)
182 md_atof (int type
, char *litP
, int *sizeP
)
184 return ieee_md_atof (type
, litP
, sizeP
, TRUE
);
188 md_section_align (asection
*seg
, valueT addr
)
190 int align
= bfd_section_alignment (seg
);
191 return ((addr
+ (1 << align
) - 1) & -(1 << align
));
200 s12z_init_after_args (void)
202 if (flag_traditional_format
)
203 literal_prefix_dollar_hex
= TRUE
;
210 skip_whites (char *p
)
212 while (*p
== ' ' || *p
== '\t')
220 /* Start a new insn that contains at least 'size' bytes. Record the
221 line information of that insn in the dwarf2 debug sections. */
223 s12z_new_insn (int size
)
225 char *f
= frag_more (size
);
227 dwarf2_emit_insn (size
);
234 static bfd_boolean
lex_reg_name (uint16_t which
, int *reg
);
237 lex_constant (long *v
)
240 char *p
= input_line_pointer
;
242 /* A constant may not have the same value as a register
245 if (lex_reg_name (~0, &dummy
))
247 input_line_pointer
= p
;
252 *v
= s12z_strtol (p
, &end
);
253 if (errno
== 0 && end
!= p
)
255 input_line_pointer
= end
;
265 char *p
= input_line_pointer
;
269 input_line_pointer
++;
275 lex_expression (expressionS
*exp
)
277 char *ilp
= input_line_pointer
;
279 exp
->X_op
= O_absent
;
284 if (lex_reg_name (~0, &dummy
))
288 if (exp
->X_op
!= O_absent
)
292 fail_line_pointer
= input_line_pointer
;
293 input_line_pointer
= ilp
;
297 /* Immediate operand.
298 If EXP_O is non-null, then a symbolic expression is permitted,
299 in which case, EXP_O will be populated with the parsed expression.
302 lex_imm (long *v
, expressionS
*exp_o
)
304 char *ilp
= input_line_pointer
;
306 if (*input_line_pointer
!= '#')
309 input_line_pointer
++;
311 if (!lex_expression (&exp
))
314 if (exp
.X_op
!= O_constant
)
317 as_bad (_("A non-constant expression is not permitted here"));
322 *v
= exp
.X_add_number
;
326 fail_line_pointer
= input_line_pointer
;
327 input_line_pointer
= ilp
;
331 /* Short mmediate operand */
333 lex_imm_e4 (long *val
)
335 char *ilp
= input_line_pointer
;
336 if ((lex_imm (val
, NULL
)))
338 if ((*val
== -1) || (*val
> 0 && *val
<= 15))
343 fail_line_pointer
= input_line_pointer
;
344 input_line_pointer
= ilp
;
349 lex_match_string (const char *s
)
351 char *p
= input_line_pointer
;
352 while (p
!= 0 && *p
!= '\t' && *p
!= ' ' && *p
!= '\0')
357 size_t len
= p
- input_line_pointer
;
358 if (len
!= strlen (s
))
361 if (0 == strncasecmp (s
, input_line_pointer
, len
))
363 input_line_pointer
= p
;
370 /* Parse a register name.
371 WHICH is a ORwise combination of the registers which are accepted.
373 On success, REG will be filled with the index of the register which
374 was successfully scanned.
377 lex_reg_name (uint16_t which
, int *reg
)
379 char *p
= input_line_pointer
;
384 /* Scan (and ignore) the register prefix. */
387 int len
= strlen (register_prefix
);
388 if (0 == strncmp (register_prefix
, p
, len
))
394 char *start_of_reg_name
= p
;
396 while ((*p
>= 'a' && *p
<='z')
397 || (*p
>= '0' && *p
<= '9')
398 || (*p
>= 'A' && *p
<='Z'))
403 size_t len
= p
- start_of_reg_name
;
409 for (i
= 0; i
< S12Z_N_REGISTERS
; ++i
)
411 gas_assert (registers
[i
].name
);
413 if (len
== strlen (registers
[i
].name
)
414 && 0 == strncasecmp (registers
[i
].name
, start_of_reg_name
, len
))
416 if ((0x1U
<< i
) & which
)
418 input_line_pointer
= p
;
429 lex_force_match (char x
)
431 char *p
= input_line_pointer
;
434 as_bad (_("Expecting '%c'"), x
);
438 input_line_pointer
++;
443 lex_opr (uint8_t *buffer
, int *n_bytes
, expressionS
*exp
,
446 char *ilp
= input_line_pointer
;
447 uint8_t *xb
= buffer
;
450 exp
->X_op
= O_absent
;
453 if (lex_imm_e4 (&imm
))
457 as_bad (_("An immediate value in a source operand is inappropriate"));
468 else if (lex_reg_name (REG_BIT_Dn
, ®
))
475 else if (lex_match ('['))
477 if (lex_expression (exp
))
479 long c
= exp
->X_add_number
;
482 if (lex_reg_name (REG_BIT_XYSP
, ®
))
485 if (c
<= 255 && c
>= -256)
495 *xb
|= (reg
- REG_X
) << 4;
499 for (i
= 1; i
< *n_bytes
; ++i
)
501 buffer
[i
] = c
>> (8 * (*n_bytes
- i
- 1));
506 as_bad (_("Bad operand for constant offset"));
519 else if (lex_reg_name (REG_BIT_Dn
, ®
))
521 if (!lex_force_match (','))
525 if (lex_reg_name (REG_BIT_XY
, ®2
))
529 *xb
|= (reg2
- REG_X
) << 4;
534 as_bad (_("Invalid operand for register offset"));
542 if (!lex_force_match (']'))
546 else if (lex_match ('('))
549 if (lex_constant (&c
))
551 if (!lex_force_match (','))
554 if (lex_reg_name (REG_BIT_XYSP
, ®2
))
556 if (reg2
!= REG_P
&& c
>= 0 && c
<= 15)
560 *xb
|= (reg2
- REG_X
) << 4;
563 else if (c
>= -256 && c
<= 255)
567 *xb
|= (reg2
- REG_X
) << 4;
576 *xb
|= (reg2
- REG_X
) << 4;
582 else if (lex_reg_name (REG_BIT_Dn
, ®2
))
584 if (c
>= -1 * (long) (0x1u
<< 17)
586 c
< (long) (0x1u
<< 17) - 1)
591 *xb
|= ((c
>> 16) & 0x03) << 4;
607 as_bad (_("Bad operand for constant offset"));
611 else if (lex_reg_name (REG_BIT_Dn
, ®
))
616 if (lex_reg_name (REG_BIT_XYS
, ®2
))
620 *xb
|= (reg2
- REG_X
) << 4;
625 as_bad (_("Invalid operand for register offset"));
634 else if (lex_reg_name (REG_BIT_XYS
, ®
))
640 as_bad (_("Invalid register for postdecrement operation"));
646 else if (reg
== REG_Y
)
649 else if (lex_match ('+'))
654 else if (reg
== REG_Y
)
656 else if (reg
== REG_S
)
664 else if (lex_match ('+'))
666 if (lex_reg_name (REG_BIT_XY
, ®
))
671 else if (reg
== REG_Y
)
676 as_bad (_("Invalid register for preincrement operation"));
680 else if (lex_match ('-'))
682 if (lex_reg_name (REG_BIT_XYS
, ®
))
687 else if (reg
== REG_Y
)
689 else if (reg
== REG_S
)
694 as_bad (_("Invalid register for predecrement operation"));
703 if (! lex_match (')'))
707 else if (lex_expression (exp
))
714 if (exp
->X_op
== O_constant
)
716 valueT value
= exp
->X_add_number
;
718 if (value
< (0x1U
<< 14))
725 else if (value
< (0x1U
<< 19))
728 if (value
& (0x1U
<< 17))
730 if (value
& (0x1U
<< 16))
733 buffer
[1] = value
>> 8;
740 buffer
[1] = value
>> 16;
741 buffer
[2] = value
>> 8;
749 fail_line_pointer
= input_line_pointer
;
750 input_line_pointer
= ilp
;
755 lex_offset (long *val
)
758 char *p
= input_line_pointer
;
763 if (*p
!= '+' && *p
!= '-')
766 bool negative
= (*p
== '-');
770 *val
= s12z_strtol (p
, &end
);
775 input_line_pointer
= end
;
786 typedef int (*parse_operand_func
) (const struct instruction
*);
792 /* The "page" to which the instruction belongs.
793 This is also only a hint. Some instructions might have modes in both
797 /* This is a hint - and only a hint - about the opcode of the instruction.
798 The parse_operand_func is free to ignore it.
802 parse_operand_func parse_operands
;
804 /* Some instructions can be encoded with a different opcode */
809 no_operands (const struct instruction
*insn
)
811 if (*input_line_pointer
!= '\0')
813 as_bad (_("Garbage at end of instruction"));
817 char *f
= s12z_new_insn (insn
->page
);
819 number_to_chars_bigendian (f
++, PAGE2_PREBYTE
, 1);
821 number_to_chars_bigendian (f
++, insn
->opc
, 1);
828 emit_reloc (expressionS
*exp
, char *f
, int size
, enum bfd_reloc_code_real reloc
)
830 if (exp
->X_op
!= O_absent
&& exp
->X_op
!= O_constant
)
832 fixS
*fix
= fix_new_exp (frag_now
,
833 f
- frag_now
->fr_literal
,
838 /* Some third party tools seem to use the lower bits
839 of this addend for flags. They don't get added
840 to the final location. The purpose of these flags
841 is not known. We simply set it to zero. */
842 fix
->fx_addnumber
= 0x00;
846 /* Emit the code for an OPR address mode operand */
848 emit_opr (char *f
, const uint8_t *buffer
, int n_bytes
, expressionS
*exp
)
851 number_to_chars_bigendian (f
++, buffer
[0], 1);
853 emit_reloc (exp
, f
, 3, BFD_RELOC_S12Z_OPR
);
855 for (i
= 1; i
< n_bytes
; ++i
)
856 number_to_chars_bigendian (f
++, buffer
[i
], 1);
861 /* Emit the code for a 24 bit direct address operand */
863 emit_ext24 (char *f
, long v
)
865 number_to_chars_bigendian (f
, v
, 3);
871 opr (const struct instruction
*insn
)
876 if (lex_opr (buffer
, &n_bytes
, &exp
, false))
878 /* Large constant direct values are more efficiently encoded as ext24 mode.
879 Otherwise a decision has to be deferred to a relax. */
880 if (exp
.X_op
== O_constant
882 && insn
->alt_opc
!= 0)
884 char *f
= s12z_new_insn (4);
886 /* I don't think there are any instances of page 2 opcodes in this case */
887 gas_assert (insn
->page
== 1);
889 number_to_chars_bigendian (f
++, insn
->alt_opc
, 1);
891 emit_ext24 (f
, exp
.X_add_number
);
895 char *f
= s12z_new_insn (n_bytes
+ 1);
896 number_to_chars_bigendian (f
++, insn
->opc
, 1);
898 emit_opr (f
, buffer
, n_bytes
, &exp
);
906 /* Parse a 15 bit offset, as an expression.
907 LONG_DISPLACEMENT will be set to true if the offset is wider than 7 bits.
910 lex_15_bit_offset (bool *long_displacement
, expressionS
*exp
)
912 char *ilp
= input_line_pointer
;
915 if (lex_offset (&val
))
917 exp
->X_op
= O_absent
;
918 exp
->X_add_number
= val
;
920 else if (lex_expression (exp
))
922 if (exp
->X_op
== O_constant
)
924 val
= exp
->X_add_number
;
928 /* If a symbol was parsed we don't know the displacement.
929 We have to assume it is long, and relax it later if possible. */
930 *long_displacement
= true;
936 exp
->X_op
= O_absent
;
940 if (val
> 0x3FFF || val
< -0x4000)
942 as_fatal (_("Offset is outside of 15 bit range"));
946 *long_displacement
= (val
> 63 || val
< -64);
951 fail_line_pointer
= input_line_pointer
;
952 input_line_pointer
= ilp
;
957 emit_15_bit_offset (char *f
, int where
, expressionS
*exp
)
960 if (exp
->X_op
!= O_absent
&& exp
->X_op
!= O_constant
)
962 exp
->X_add_number
+= where
;
963 fixS
*fix
= fix_new_exp (frag_now
,
964 f
- frag_now
->fr_literal
,
969 fix
->fx_addnumber
= where
- 2;
973 long val
= exp
->X_add_number
;
974 bool long_displacement
= (val
> 63 || val
< -64);
975 if (long_displacement
)
980 number_to_chars_bigendian (f
++, val
, long_displacement
? 2 : 1);
985 rel (const struct instruction
*insn
)
987 bool long_displacement
;
990 if (! lex_15_bit_offset (&long_displacement
, &exp
))
993 char *f
= s12z_new_insn (long_displacement
? 3 : 2);
994 number_to_chars_bigendian (f
++, insn
->opc
, 1);
995 emit_15_bit_offset (f
, 3, &exp
);
1000 reg_inh (const struct instruction
*insn
)
1003 if (lex_reg_name (REG_BIT_Dn
, ®
))
1005 char *f
= s12z_new_insn (insn
->page
);
1006 if (insn
->page
== 2)
1007 number_to_chars_bigendian (f
++, PAGE2_PREBYTE
, 1);
1009 number_to_chars_bigendian (f
++, insn
->opc
+ reg
, 1);
1017 /* Special case for CLR X and CLR Y */
1019 clr_xy (const struct instruction
*insn ATTRIBUTE_UNUSED
)
1022 if (lex_reg_name (REG_BIT_XY
, ®
))
1024 char *f
= s12z_new_insn (1);
1025 number_to_chars_bigendian (f
, 0x9a + reg
- REG_X
, 1);
1032 /* Some instructions have a suffix like ".l", ".b", ".w" etc
1033 which indicates the size of the operands. */
1035 size_from_suffix (const struct instruction
*insn
, int idx
)
1037 const char *dot
= strchr (insn
->name
, '.');
1043 switch (dot
[1 + idx
])
1058 as_fatal (_("Bad size"));
1065 mul_reg_reg_reg (const struct instruction
*insn
)
1067 char *ilp
= input_line_pointer
;
1070 if (!lex_reg_name (REG_BIT_Dn
, &Dd
))
1073 if (!lex_match (','))
1077 if (!lex_reg_name (REG_BIT_Dn
, &Dj
))
1080 if (!lex_match (','))
1084 if (!lex_reg_name (REG_BIT_Dn
, &Dk
))
1087 char *f
= s12z_new_insn (insn
->page
+ 1);
1088 if (insn
->page
== 2)
1089 number_to_chars_bigendian (f
++, PAGE2_PREBYTE
, 1);
1091 number_to_chars_bigendian (f
++, insn
->opc
+ Dd
, 1);
1092 const char *dot
= strchrnul (insn
->name
, '.');
1103 as_fatal (_("BAD MUL"));
1110 number_to_chars_bigendian (f
++, mb
, 1);
1115 fail_line_pointer
= input_line_pointer
;
1116 input_line_pointer
= ilp
;
1122 mul_reg_reg_imm (const struct instruction
*insn
)
1124 char *ilp
= input_line_pointer
;
1127 if (!lex_reg_name (REG_BIT_Dn
, &Dd
))
1130 if (!lex_match (','))
1134 if (!lex_reg_name (REG_BIT_Dn
, &Dj
))
1137 if (!lex_match (','))
1141 if (!lex_imm (&imm
, NULL
))
1145 int size
= size_from_suffix (insn
, 0);
1147 char *f
= s12z_new_insn (insn
->page
+ 1 + size
);
1148 if (insn
->page
== 2)
1149 number_to_chars_bigendian (f
++, PAGE2_PREBYTE
, 1);
1151 number_to_chars_bigendian (f
++, insn
->opc
+ Dd
, 1);
1153 const char *dot
= strchrnul (insn
->name
, '.');
1163 as_fatal (_("BAD MUL"));
1170 number_to_chars_bigendian (f
++, mb
, 1);
1171 number_to_chars_bigendian (f
++, imm
, size
);
1176 fail_line_pointer
= input_line_pointer
;
1177 input_line_pointer
= ilp
;
1183 mul_reg_reg_opr (const struct instruction
*insn
)
1185 char *ilp
= input_line_pointer
;
1188 if (!lex_reg_name (REG_BIT_Dn
, &Dd
))
1191 if (!lex_match (','))
1195 if (!lex_reg_name (REG_BIT_Dn
, &Dj
))
1198 if (!lex_match (','))
1204 if (!lex_opr (buffer
, &n_bytes
, &exp
, true))
1207 int size
= size_from_suffix (insn
, 0);
1209 char *f
= s12z_new_insn (insn
->page
+ 1 + n_bytes
);
1210 if (insn
->page
== 2)
1211 number_to_chars_bigendian (f
++, PAGE2_PREBYTE
, 1);
1213 number_to_chars_bigendian (f
++, insn
->opc
+ Dd
, 1);
1215 const char *dot
= strchrnul (insn
->name
, '.');
1225 as_fatal (_("BAD MUL"));
1232 number_to_chars_bigendian (f
++, mb
, 1);
1234 emit_opr (f
, buffer
, n_bytes
, &exp
);
1239 fail_line_pointer
= input_line_pointer
;
1240 input_line_pointer
= ilp
;
1245 mul_reg_opr_opr (const struct instruction
*insn
)
1247 char *ilp
= input_line_pointer
;
1250 if (!lex_reg_name (REG_BIT_Dn
, &Dd
))
1253 if (!lex_match (','))
1259 if (!lex_opr (buffer1
, &n_bytes1
, &exp1
, false))
1262 if (!lex_match (','))
1268 if (!lex_opr (buffer2
, &n_bytes2
, &exp2
, false))
1271 int size1
= size_from_suffix (insn
, 0);
1272 int size2
= size_from_suffix (insn
, 1);
1274 char *f
= s12z_new_insn (insn
->page
+ 1 + n_bytes1
+ n_bytes2
);
1275 if (insn
->page
== 2)
1276 number_to_chars_bigendian (f
++, PAGE2_PREBYTE
, 1);
1278 number_to_chars_bigendian (f
++, insn
->opc
+ Dd
, 1);
1280 const char *dot
= strchrnul (insn
->name
, '.');
1290 as_fatal (_("BAD MUL"));
1294 mb
|= (size1
- 1) << 4;
1295 mb
|= (size2
- 1) << 2;
1296 number_to_chars_bigendian (f
++, mb
, 1);
1298 f
= emit_opr (f
, buffer1
, n_bytes1
, &exp1
);
1299 f
= emit_opr (f
, buffer2
, n_bytes2
, &exp2
);
1304 fail_line_pointer
= input_line_pointer
;
1305 input_line_pointer
= ilp
;
1310 #define REG_BIT_GRP0 \
1311 ((0x1U << REG_D2) | \
1312 (0x1U << REG_D3) | \
1313 (0x1U << REG_CCH) | \
1314 (0x1U << REG_CCL) | \
1315 (0x1U << REG_D0) | \
1318 #define REG_BIT_GRP1 \
1319 ((0x1U << REG_D4) | \
1320 (0x1U << REG_D5) | \
1321 (0x1U << REG_D6) | \
1322 (0x1U << REG_D7) | \
1326 static const uint8_t reg_map
[] =
1346 lex_reg_list (uint16_t grp
, uint16_t *reg_bits
)
1348 if (lex_match (','))
1351 if (!lex_reg_name (grp
, ®
))
1353 *reg_bits
|= 0x1u
<< reg
;
1354 lex_reg_list (grp
, reg_bits
);
1362 psh_pull (const struct instruction
*insn
)
1365 (0 == strcmp ("pul", insn
->name
)) ? 0x80: 0x00;
1367 if (lex_match_string ("all16b"))
1371 else if (lex_match_string ("all"))
1378 if (!lex_reg_name (REG_BIT_GRP1
| REG_BIT_GRP0
, ®1
))
1380 uint16_t admitted_group
= 0;
1382 if ((0x1U
<< reg1
) & REG_BIT_GRP1
)
1383 admitted_group
= REG_BIT_GRP1
;
1384 else if ((0x1U
<< reg1
) & REG_BIT_GRP0
)
1385 admitted_group
= REG_BIT_GRP0
;
1387 uint16_t reg_bits
= 0x1 << reg1
;
1388 if (!lex_reg_list (admitted_group
, ®_bits
))
1391 if (reg_bits
& REG_BIT_GRP1
)
1395 for (i
= 0; i
< 16; ++i
)
1397 if (reg_bits
& (0x1u
<< i
))
1402 char *f
= s12z_new_insn (2);
1403 number_to_chars_bigendian (f
++, insn
->opc
, 1);
1404 number_to_chars_bigendian (f
++, pb
, 1);
1408 fail_line_pointer
= input_line_pointer
;
1414 tfr (const struct instruction
*insn
)
1417 if (!lex_reg_name (~0, ®1
))
1420 if (!lex_match (','))
1424 if (!lex_reg_name (~0, ®2
))
1427 if ( ((0 == strcasecmp ("sex", insn
->name
))
1428 || (0 == strcasecmp ("zex", insn
->name
)))
1429 && (registers
[reg2
].bytes
<= registers
[reg1
].bytes
))
1430 as_warn (_("Source register for %s is no larger than the destination register"),
1432 else if (reg1
== reg2
)
1433 as_warn (_("The destination and source registers are identical"));
1435 char *f
= s12z_new_insn (1 + insn
->page
);
1436 if (insn
->page
== 2)
1437 number_to_chars_bigendian (f
++, PAGE2_PREBYTE
, 1);
1439 number_to_chars_bigendian (f
++, insn
->opc
, 1);
1440 number_to_chars_bigendian (f
++, reg1
<< 4 | reg2
, 1);
1445 fail_line_pointer
= input_line_pointer
;
1450 imm8 (const struct instruction
*insn
)
1453 if (! lex_imm (&imm
, NULL
))
1455 if (imm
> 127 || imm
< -128)
1457 as_bad (_("Immediate value %ld is out of range for instruction %s"),
1461 char *f
= s12z_new_insn (2);
1462 number_to_chars_bigendian (f
++, insn
->opc
, 1);
1463 number_to_chars_bigendian (f
++, imm
, 1);
1469 reg_imm (const struct instruction
*insn
, int allowed_reg
)
1471 char *ilp
= input_line_pointer
;
1473 if (lex_reg_name (allowed_reg
, ®
))
1475 if (!lex_force_match (','))
1478 if (! lex_imm (&imm
, NULL
))
1481 short size
= registers
[reg
].bytes
;
1482 char *f
= s12z_new_insn (insn
->page
+ size
);
1483 if (insn
->page
== 2)
1484 number_to_chars_bigendian (f
++, PAGE2_PREBYTE
, 1);
1486 number_to_chars_bigendian (f
++, insn
->opc
+ reg
, 1);
1487 number_to_chars_bigendian (f
++, imm
, size
);
1492 fail_line_pointer
= input_line_pointer
;
1493 input_line_pointer
= ilp
;
1499 regd_imm (const struct instruction
*insn
)
1501 return reg_imm (insn
, REG_BIT_Dn
);
1505 regdxy_imm (const struct instruction
*insn
)
1507 return reg_imm (insn
, REG_BIT_Dn
| REG_BIT_XY
);
1512 regs_imm (const struct instruction
*insn
)
1514 return reg_imm (insn
, 0x1U
<< REG_S
);
1518 trap_imm (const struct instruction
*insn ATTRIBUTE_UNUSED
)
1521 if (! lex_imm (&imm
, NULL
))
1524 if (imm
< 0x92 || imm
> 0xFF ||
1525 (imm
>= 0xA0 && imm
<= 0xA7) ||
1526 (imm
>= 0xB0 && imm
<= 0xB7))
1528 as_bad (_("trap value %ld is not valid"), imm
);
1533 char *f
= s12z_new_insn (2);
1534 number_to_chars_bigendian (f
++, PAGE2_PREBYTE
, 1);
1535 number_to_chars_bigendian (f
++, imm
& 0xFF, 1);
1542 fail_line_pointer
= input_line_pointer
;
1548 /* Special one byte instruction CMP X, Y */
1550 regx_regy (const struct instruction
*insn
)
1553 if (lex_reg_name (0x1U
<< REG_X
, ®
))
1555 if (lex_force_match (','))
1557 if (lex_reg_name (0x1U
<< REG_Y
, ®
))
1559 char *f
= s12z_new_insn (1);
1560 number_to_chars_bigendian (f
, insn
->opc
, 1);
1568 /* Special one byte instruction SUB D6, X, Y */
1570 regd6_regx_regy (const struct instruction
*insn
)
1572 char *ilp
= input_line_pointer
;
1574 if (!lex_reg_name (0x1U
<< REG_D6
, ®
))
1577 if (!lex_match (','))
1580 if (!lex_reg_name (0x1U
<< REG_X
, ®
))
1583 if (!lex_match (','))
1586 if (!lex_reg_name (0x1U
<< REG_Y
, ®
))
1589 char *f
= s12z_new_insn (1);
1590 number_to_chars_bigendian (f
, insn
->opc
, 1);
1594 fail_line_pointer
= input_line_pointer
;
1595 input_line_pointer
= ilp
;
1599 /* Special one byte instruction SUB D6, Y, X */
1601 regd6_regy_regx (const struct instruction
*insn
)
1603 char *ilp
= input_line_pointer
;
1605 if (!lex_reg_name (0x1U
<< REG_D6
, ®
))
1608 if (!lex_match (','))
1611 if (!lex_reg_name (0x1U
<< REG_Y
, ®
))
1614 if (!lex_match (','))
1617 if (!lex_reg_name (0x1U
<< REG_X
, ®
))
1620 char *f
= s12z_new_insn (1);
1621 number_to_chars_bigendian (f
, insn
->opc
, 1);
1625 fail_line_pointer
= input_line_pointer
;
1626 input_line_pointer
= ilp
;
1631 reg_opr (const struct instruction
*insn
, int allowed_regs
,
1634 char *ilp
= input_line_pointer
;
1636 if (lex_reg_name (allowed_regs
, ®
))
1638 if (!lex_force_match (','))
1644 if (lex_opr (buffer
, &n_bytes
, &exp
, immediate_ok
))
1646 /* Large constant direct values are more efficiently encoded as ext24 mode.
1647 Otherwise a decision has to be deferred to a relax. */
1648 if (exp
.X_op
== O_constant
1649 && buffer
[0] == 0xFA
1650 && insn
->alt_opc
!= 0)
1652 char *f
= s12z_new_insn (4);
1654 /* I don't think there are any instances of page 2 opcodes in this case */
1655 gas_assert (insn
->page
== 1);
1657 number_to_chars_bigendian (f
++, insn
->alt_opc
+ reg
, 1);
1659 emit_ext24 (f
, exp
.X_add_number
);
1663 char *f
= s12z_new_insn (n_bytes
+ insn
->page
);
1665 if (insn
->page
== 2)
1666 number_to_chars_bigendian (f
++, PAGE2_PREBYTE
, 1);
1668 number_to_chars_bigendian (f
++, insn
->opc
+ reg
, 1);
1670 emit_opr (f
, buffer
, n_bytes
, &exp
);
1678 fail_line_pointer
= input_line_pointer
;
1679 input_line_pointer
= ilp
;
1685 regdxy_opr_dest (const struct instruction
*insn
)
1687 return reg_opr (insn
, REG_BIT_Dn
| REG_BIT_XY
, false);
1691 regdxy_opr_src (const struct instruction
*insn
)
1693 return reg_opr (insn
, REG_BIT_Dn
| REG_BIT_XY
, true);
1698 regd_opr (const struct instruction
*insn
)
1700 return reg_opr (insn
, REG_BIT_Dn
, true);
1704 /* OP0: S; OP1: destination OPR */
1706 regs_opr_dest (const struct instruction
*insn
)
1708 return reg_opr (insn
, 0x1U
<< REG_S
, false);
1711 /* OP0: S; OP1: source OPR */
1713 regs_opr_src (const struct instruction
*insn
)
1715 return reg_opr (insn
, 0x1U
<< REG_S
, true);
1719 imm_opr (const struct instruction
*insn
)
1721 char *ilp
= input_line_pointer
;
1724 int size
= size_from_suffix (insn
, 0);
1725 exp0
.X_op
= O_absent
;
1727 /* Note: The ternary expression below means that "MOV.x #symbol,
1728 mem-expr" is accepted when x is a member of {'w', 'p', 'l'} but
1730 The Freescale assembler accepts "MOV.b #symbol, mem-expr" but
1731 produces obviously incorrect code. Since such an instruction
1732 would require an 8-bit reloc (which we don't have) and some
1733 non-optimal kludges in the OPR encoding, it seems sensible that
1734 such instructions should be rejected. */
1735 if (!lex_imm (&imm
, size
> 1 ? &exp0
: NULL
))
1738 if (!lex_match (','))
1744 if (!lex_opr (buffer
, &n_bytes
, &exp1
, false))
1747 char *f
= s12z_new_insn (1 + n_bytes
+ size
);
1748 number_to_chars_bigendian (f
++, insn
->opc
, 1);
1750 emit_reloc (&exp0
, f
, size
, size
== 4 ? BFD_RELOC_32
: BFD_RELOC_S12Z_OPR
);
1753 for (i
= 0; i
< size
; ++i
)
1754 number_to_chars_bigendian (f
++, imm
>> (CHAR_BIT
* (size
- i
- 1)), 1);
1756 emit_opr (f
, buffer
, n_bytes
, &exp1
);
1761 fail_line_pointer
= input_line_pointer
;
1762 input_line_pointer
= ilp
;
1767 opr_opr (const struct instruction
*insn
)
1769 char *ilp
= input_line_pointer
;
1774 if (!lex_opr (buffer1
, &n_bytes1
, &exp1
, false))
1778 if (!lex_match (','))
1784 if (!lex_opr (buffer2
, &n_bytes2
, &exp2
, false))
1787 char *f
= s12z_new_insn (1 + n_bytes1
+ n_bytes2
);
1788 number_to_chars_bigendian (f
++, insn
->opc
, 1);
1790 f
= emit_opr (f
, buffer1
, n_bytes1
, &exp1
);
1791 f
= emit_opr (f
, buffer2
, n_bytes2
, &exp2
);
1796 fail_line_pointer
= input_line_pointer
;
1797 input_line_pointer
= ilp
;
1802 reg67sxy_opr (const struct instruction
*insn
)
1805 if (!lex_reg_name (REG_BIT_XYS
| (0x1U
<< REG_D6
) | (0x1U
<< REG_D7
), ®
))
1808 if (!lex_match (','))
1814 if (!lex_opr (buffer
, &n_bytes
, &exp
, false))
1817 char *f
= s12z_new_insn (1 + n_bytes
);
1818 number_to_chars_bigendian (f
++, insn
->opc
+ reg
- REG_D6
, 1);
1819 emit_opr (f
, buffer
, n_bytes
, &exp
);
1825 rotate (const struct instruction
*insn
, short dir
)
1830 if (lex_opr (buffer
, &n_bytes
, &exp
, false))
1832 char *f
= s12z_new_insn (n_bytes
+ 2);
1833 number_to_chars_bigendian (f
++, insn
->opc
, 1);
1834 int size
= size_from_suffix (insn
, 0);
1841 number_to_chars_bigendian (f
++, sb
, 1);
1842 emit_opr (f
, buffer
, n_bytes
, &exp
);
1851 rol (const struct instruction
*insn
)
1853 return rotate (insn
, 1);
1857 ror (const struct instruction
*insn
)
1859 return rotate (insn
, 0);
1863 /* Shift instruction with a register operand and an immediate #1 or #2
1864 left = 1; right = 0;
1865 logical = 0; arithmetic = 1;
1868 lex_shift_reg_imm1 (const struct instruction
*insn
, short type
, short dir
)
1871 This function is highly unusual and a bit wierd!
1872 It first matches the input against a register {d0, d1, ... d7} followed by an immediate
1874 Then, it rewinds the input and parses it again as a OPR.
1876 char *ilp
= input_line_pointer
;
1879 if (!lex_reg_name (REG_BIT_Dn
, &Dd
))
1884 if (!lex_match (','))
1888 if (!lex_imm (&imm
, NULL
))
1891 if (imm
!= 1 && imm
!= 2)
1893 input_line_pointer
= ilp
;
1895 /* Now parse the first operand again */
1901 if (!lex_opr (buffer
, &n_bytes
, &exp
, false))
1904 gas_assert (n_bytes
== 1);
1912 char *f
= s12z_new_insn (3);
1913 number_to_chars_bigendian (f
++, insn
->opc
, 1);
1914 number_to_chars_bigendian (f
++, sb
, 1);
1915 emit_opr (f
, buffer
, n_bytes
, &exp
);
1920 fail_line_pointer
= input_line_pointer
;
1921 input_line_pointer
= ilp
;
1925 /* Shift instruction with a register operand.
1926 left = 1; right = 0;
1927 logical = 0; arithmetic = 1; */
1929 lex_shift_reg (const struct instruction
*insn
, short type
, short dir
)
1932 if (!lex_reg_name (REG_BIT_Dn
, &Dd
))
1937 if (!lex_match (','))
1940 if (!lex_reg_name (REG_BIT_Dn
, &Ds
))
1945 if (!lex_match (','))
1953 if (lex_reg_name (REG_BIT_Dn
, &Dn
))
1955 char *f
= s12z_new_insn (3);
1956 number_to_chars_bigendian (f
++, insn
->opc
| Dd
, 1);
1957 number_to_chars_bigendian (f
++, sb
, 1);
1960 number_to_chars_bigendian (f
++, xb
, 1);
1964 else if (lex_imm (&imm
, NULL
))
1966 if (imm
< 0 || imm
> 31)
1968 as_bad (_("Shift value should be in the range [0,31]"));
1973 if (imm
== 1 || imm
== 2)
1980 sb
|= (imm
& 0x01) << 3;
1983 char *f
= s12z_new_insn (n_bytes
);
1984 number_to_chars_bigendian (f
++, insn
->opc
| Dd
, 1);
1985 number_to_chars_bigendian (f
++, sb
, 1);
1990 number_to_chars_bigendian (f
++, xb
, 1);
1997 fail_line_pointer
= input_line_pointer
;
2002 impute_shift_dir_and_type (const struct instruction
*insn
, short *type
, short *dir
)
2006 switch (insn
->name
[0])
2015 as_fatal (_("Bad shift mode"));
2019 switch (insn
->name
[2])
2028 as_fatal (_("Bad shift *direction"));
2033 /* Shift instruction with a OPR operand */
2035 shift_two_operand (const struct instruction
*insn
)
2038 char *ilp
= input_line_pointer
;
2042 impute_shift_dir_and_type (insn
, &type
, &dir
);
2046 int size
= size_from_suffix (insn
, 0);
2052 if (!lex_opr (buffer
, &n_opr_bytes
, &exp
, false))
2055 if (!lex_match (','))
2059 if (!lex_imm (&imm
, NULL
))
2062 if (imm
!= 1 && imm
!= 2)
2068 char *f
= s12z_new_insn (2 + n_opr_bytes
);
2069 number_to_chars_bigendian (f
++, insn
->opc
, 1);
2070 number_to_chars_bigendian (f
++, sb
, 1);
2071 emit_opr (f
, buffer
, n_opr_bytes
, &exp
);
2076 fail_line_pointer
= input_line_pointer
;
2077 input_line_pointer
= ilp
;
2081 /* Shift instruction with a OPR operand */
2083 shift_opr_imm (const struct instruction
*insn
)
2085 char *ilp
= input_line_pointer
;
2089 impute_shift_dir_and_type (insn
, &type
, &dir
);
2092 if (!lex_reg_name (REG_BIT_Dn
, &Dd
))
2095 if (!lex_match (','))
2104 if (!lex_opr (buffer1
, &n_opr_bytes1
, &exp1
, false))
2107 n_bytes
+= n_opr_bytes1
;
2108 if (!lex_match (','))
2112 int n_opr_bytes2
= 0;
2115 bool immediate
= false;
2116 if (lex_imm (&imm
, NULL
))
2120 else if (!lex_opr (buffer2
, &n_opr_bytes2
, &exp2
, false))
2125 int size
= size_from_suffix (insn
, 0);
2135 if (imm
== 2 || imm
== 1)
2150 n_bytes
+= n_opr_bytes2
;
2154 char *f
= s12z_new_insn (n_bytes
);
2155 number_to_chars_bigendian (f
++, insn
->opc
| Dd
, 1);
2156 number_to_chars_bigendian (f
++, sb
, 1);
2157 f
= emit_opr (f
, buffer1
, n_opr_bytes1
, &exp1
);
2160 if (imm
!= 1 && imm
!= 2)
2162 number_to_chars_bigendian (f
++, 0x70 | (imm
>> 1), 1);
2167 f
= emit_opr (f
, buffer2
, n_opr_bytes2
, &exp2
);
2173 fail_line_pointer
= input_line_pointer
;
2174 input_line_pointer
= ilp
;
2178 /* Shift instruction with a register operand */
2180 shift_reg (const struct instruction
*insn
)
2184 impute_shift_dir_and_type (insn
, &type
, &dir
);
2186 if (lex_shift_reg_imm1 (insn
, type
, dir
))
2189 return lex_shift_reg (insn
, type
, dir
);
2193 bm_regd_imm (const struct instruction
*insn
)
2195 char *ilp
= input_line_pointer
;
2197 if (!lex_reg_name (REG_BIT_Dn
, &Di
))
2200 if (!lex_match (','))
2204 if (!lex_imm (&imm
, NULL
))
2208 uint8_t bm
= imm
<< 3;
2211 char *f
= s12z_new_insn (2);
2212 number_to_chars_bigendian (f
++, insn
->opc
, 1);
2213 number_to_chars_bigendian (f
++, bm
, 1);
2218 fail_line_pointer
= input_line_pointer
;
2219 input_line_pointer
= ilp
;
2224 bm_opr_reg (const struct instruction
*insn
)
2226 char *ilp
= input_line_pointer
;
2232 if (!lex_opr (buffer
, &n_opr_bytes
, &exp
, false))
2235 if (!lex_match (','))
2239 if (!lex_reg_name (REG_BIT_Dn
, &Dn
))
2242 uint8_t bm
= Dn
<< 4;
2243 int size
= size_from_suffix (insn
, 0);
2244 bm
|= (size
- 1) << 2;
2247 char *f
= s12z_new_insn (2 + n_opr_bytes
);
2248 number_to_chars_bigendian (f
++, insn
->opc
, 1);
2249 number_to_chars_bigendian (f
++, bm
, 1);
2251 emit_opr (f
, buffer
, n_opr_bytes
, &exp
);
2256 fail_line_pointer
= input_line_pointer
;
2257 input_line_pointer
= ilp
;
2263 bm_opr_imm (const struct instruction
*insn
)
2265 char *ilp
= input_line_pointer
;
2271 if (!lex_opr (buffer
, &n_opr_bytes
, &exp
, false))
2274 if (!lex_match (','))
2279 if (!lex_imm (&imm
, NULL
))
2282 int size
= size_from_suffix (insn
, 0);
2284 if (imm
< 0 || imm
>= size
* 8)
2286 as_bad (_("Immediate operand %ld is inappropriate for size of instruction"), imm
);
2295 bm
|= (imm
& 0x07) << 4;
2299 char *f
= s12z_new_insn (2 + n_opr_bytes
);
2300 number_to_chars_bigendian (f
++, insn
->opc
, 1);
2301 number_to_chars_bigendian (f
++, bm
, 1);
2302 emit_opr (f
, buffer
, n_opr_bytes
, &exp
);
2307 fail_line_pointer
= input_line_pointer
;
2308 input_line_pointer
= ilp
;
2314 bm_regd_reg (const struct instruction
*insn
)
2316 char *ilp
= input_line_pointer
;
2318 if (!lex_reg_name (REG_BIT_Dn
, &Di
))
2321 if (!lex_match (','))
2325 if (!lex_reg_name (REG_BIT_Dn
, &Dn
))
2328 uint8_t bm
= Dn
<< 4;
2331 uint8_t xb
= Di
| 0xb8;
2333 char *f
= s12z_new_insn (3);
2334 number_to_chars_bigendian (f
++, insn
->opc
, 1);
2335 number_to_chars_bigendian (f
++, bm
, 1);
2336 number_to_chars_bigendian (f
++, xb
, 1);
2341 fail_line_pointer
= input_line_pointer
;
2342 input_line_pointer
= ilp
;
2351 bf_reg_opr_imm (const struct instruction
*insn
, short ie
)
2353 char *ilp
= input_line_pointer
;
2355 if (!lex_reg_name (REG_BIT_Dn
, &Dd
))
2358 if (!lex_match (','))
2365 if (!lex_opr (buffer
, &n_bytes
, &exp
, false))
2368 if (!lex_match (','))
2372 if (!lex_imm (&width
, NULL
))
2375 if (width
< 0 || width
> 31)
2377 as_bad (_("Invalid width value for %s"), insn
->name
);
2381 if (!lex_match (':'))
2385 if (!lex_constant (&offset
))
2388 if (offset
< 0 || offset
> 31)
2390 as_bad (_("Invalid offset value for %s"), insn
->name
);
2394 uint8_t i1
= width
<< 5;
2397 int size
= size_from_suffix (insn
, 0);
2398 uint8_t bb
= ie
? 0x80 : 0x00;
2400 bb
|= (size
- 1) << 2;
2403 char *f
= s12z_new_insn (4 + n_bytes
);
2404 number_to_chars_bigendian (f
++, PAGE2_PREBYTE
, 1);
2405 number_to_chars_bigendian (f
++, 0x08 | Dd
, 1);
2406 number_to_chars_bigendian (f
++, bb
, 1);
2407 number_to_chars_bigendian (f
++, i1
, 1);
2409 emit_opr (f
, buffer
, n_bytes
, &exp
);
2414 fail_line_pointer
= input_line_pointer
;
2415 input_line_pointer
= ilp
;
2421 bf_opr_reg_imm (const struct instruction
*insn
, short ie
)
2423 char *ilp
= input_line_pointer
;
2427 if (!lex_opr (buffer
, &n_bytes
, &exp
, false))
2430 if (!lex_match (','))
2434 if (!lex_reg_name (REG_BIT_Dn
, &Ds
))
2437 if (!lex_match (','))
2441 if (!lex_imm (&width
, NULL
))
2444 if (width
< 0 || width
> 31)
2446 as_bad (_("Invalid width value for %s"), insn
->name
);
2450 if (!lex_match (':'))
2454 if (!lex_constant (&offset
))
2457 if (offset
< 0 || offset
> 31)
2459 as_bad (_("Invalid offset value for %s"), insn
->name
);
2463 uint8_t i1
= width
<< 5;
2466 int size
= size_from_suffix (insn
, 0);
2467 uint8_t bb
= ie
? 0x80 : 0x00;
2469 bb
|= (size
- 1) << 2;
2472 char *f
= s12z_new_insn (4 + n_bytes
);
2473 number_to_chars_bigendian (f
++, PAGE2_PREBYTE
, 1);
2474 number_to_chars_bigendian (f
++, 0x08 | Ds
, 1);
2475 number_to_chars_bigendian (f
++, bb
, 1);
2476 number_to_chars_bigendian (f
++, i1
, 1);
2478 emit_opr (f
, buffer
, n_bytes
, &exp
);
2483 fail_line_pointer
= input_line_pointer
;
2484 input_line_pointer
= ilp
;
2491 bf_reg_reg_imm (const struct instruction
*insn
, short ie
)
2493 char *ilp
= input_line_pointer
;
2495 if (!lex_reg_name (REG_BIT_Dn
, &Dd
))
2498 if (!lex_match (','))
2502 if (!lex_reg_name (REG_BIT_Dn
, &Ds
))
2505 if (!lex_match (','))
2509 if (!lex_imm (&width
, NULL
))
2512 if (width
< 0 || width
> 31)
2514 as_bad (_("Invalid width value for %s"), insn
->name
);
2518 if (!lex_match (':'))
2522 if (!lex_constant (&offset
))
2525 if (offset
< 0 || offset
> 31)
2527 as_bad (_("Invalid offset value for %s"), insn
->name
);
2531 uint8_t bb
= ie
? 0x80 : 0x00;
2536 uint8_t i1
= width
<< 5;
2539 char *f
= s12z_new_insn (4);
2540 number_to_chars_bigendian (f
++, PAGE2_PREBYTE
, 1);
2541 number_to_chars_bigendian (f
++, 0x08 | Dd
, 1);
2542 number_to_chars_bigendian (f
++, bb
, 1);
2543 number_to_chars_bigendian (f
++, i1
, 1);
2548 fail_line_pointer
= input_line_pointer
;
2549 input_line_pointer
= ilp
;
2554 bf_reg_reg_reg (const struct instruction
*insn ATTRIBUTE_UNUSED
, short ie
)
2556 char *ilp
= input_line_pointer
;
2558 if (!lex_reg_name (REG_BIT_Dn
, &Dd
))
2561 if (!lex_match (','))
2565 if (!lex_reg_name (REG_BIT_Dn
, &Ds
))
2568 if (!lex_match (','))
2572 if (!lex_reg_name ((0x01u
<< REG_D2
) |
2579 uint8_t bb
= ie
? 0x80 : 0x00;
2583 char *f
= s12z_new_insn (3);
2584 number_to_chars_bigendian (f
++, PAGE2_PREBYTE
, 1);
2585 number_to_chars_bigendian (f
++, 0x08 | Dd
, 1);
2586 number_to_chars_bigendian (f
++, bb
, 1);
2591 fail_line_pointer
= input_line_pointer
;
2592 input_line_pointer
= ilp
;
2597 bf_opr_reg_reg (const struct instruction
*insn
, short ie
)
2599 char *ilp
= input_line_pointer
;
2604 if (!lex_opr (buffer
, &n_bytes
, &exp
, false))
2607 if (!lex_match (','))
2612 if (!lex_reg_name (REG_BIT_Dn
, &Ds
))
2615 if (!lex_match (','))
2620 if (!lex_reg_name ((0x01u
<< REG_D2
) |
2627 int size
= size_from_suffix (insn
, 0);
2628 uint8_t bb
= ie
? 0x80 : 0x00;
2631 bb
|= (size
- 1) << 2;
2633 char *f
= s12z_new_insn (3 + n_bytes
);
2634 number_to_chars_bigendian (f
++, PAGE2_PREBYTE
, 1);
2635 number_to_chars_bigendian (f
++, 0x08 | Ds
, 1);
2636 number_to_chars_bigendian (f
++, bb
, 1);
2638 emit_opr (f
, buffer
, n_bytes
, &exp
);
2643 fail_line_pointer
= input_line_pointer
;
2644 input_line_pointer
= ilp
;
2650 bf_reg_opr_reg (const struct instruction
*insn
, short ie
)
2652 char *ilp
= input_line_pointer
;
2654 if (!lex_reg_name (REG_BIT_Dn
, &Dd
))
2657 if (!lex_match (','))
2664 if (!lex_opr (buffer
, &n_bytes
, &exp
, false))
2667 if (!lex_match (','))
2671 if (!lex_reg_name ((0x01u
<< REG_D2
) |
2678 int size
= size_from_suffix (insn
, 0);
2679 uint8_t bb
= ie
? 0x80 : 0x00;
2682 bb
|= (size
- 1) << 2;
2684 char *f
= s12z_new_insn (3 + n_bytes
);
2685 number_to_chars_bigendian (f
++, PAGE2_PREBYTE
, 1);
2686 number_to_chars_bigendian (f
++, 0x08 | Dd
, 1);
2687 number_to_chars_bigendian (f
++, bb
, 1);
2689 emit_opr (f
, buffer
, n_bytes
, &exp
);
2694 fail_line_pointer
= input_line_pointer
;
2695 input_line_pointer
= ilp
;
2702 bfe_reg_reg_reg (const struct instruction
*insn
)
2704 return bf_reg_reg_reg (insn
, 0);
2708 bfi_reg_reg_reg (const struct instruction
*insn
)
2710 return bf_reg_reg_reg (insn
, 1);
2714 bfe_reg_reg_imm (const struct instruction
*insn
)
2716 return bf_reg_reg_imm (insn
, 0);
2720 bfi_reg_reg_imm (const struct instruction
*insn
)
2722 return bf_reg_reg_imm (insn
, 1);
2727 bfe_reg_opr_reg (const struct instruction
*insn
)
2729 return bf_reg_opr_reg (insn
, 0);
2733 bfi_reg_opr_reg (const struct instruction
*insn
)
2735 return bf_reg_opr_reg (insn
, 1);
2740 bfe_opr_reg_reg (const struct instruction
*insn
)
2742 return bf_opr_reg_reg (insn
, 0);
2746 bfi_opr_reg_reg (const struct instruction
*insn
)
2748 return bf_opr_reg_reg (insn
, 1);
2752 bfe_reg_opr_imm (const struct instruction
*insn
)
2754 return bf_reg_opr_imm (insn
, 0);
2758 bfi_reg_opr_imm (const struct instruction
*insn
)
2760 return bf_reg_opr_imm (insn
, 1);
2764 bfe_opr_reg_imm (const struct instruction
*insn
)
2766 return bf_opr_reg_imm (insn
, 0);
2770 bfi_opr_reg_imm (const struct instruction
*insn
)
2772 return bf_opr_reg_imm (insn
, 1);
2779 tb_reg_rel (const struct instruction
*insn
)
2781 char *ilp
= input_line_pointer
;
2784 if (!lex_reg_name (REG_BIT_Dn
| REG_BIT_XY
, ®
))
2787 if (!lex_match (','))
2790 bool long_displacement
;
2792 if (! lex_15_bit_offset (&long_displacement
, &exp
))
2796 if (reg
== REG_X
|| reg
== REG_Y
)
2807 if (0 == strncmp (insn
->name
+ 2, "ne", 2))
2809 else if (0 == strncmp (insn
->name
+ 2, "eq", 2))
2811 else if (0 == strncmp (insn
->name
+ 2, "pl", 2))
2813 else if (0 == strncmp (insn
->name
+ 2, "mi", 2))
2815 else if (0 == strncmp (insn
->name
+ 2, "gt", 2))
2817 else if (0 == strncmp (insn
->name
+ 2, "le", 2))
2820 switch (insn
->name
[0])
2832 char *f
= s12z_new_insn (long_displacement
? 4 : 3);
2833 number_to_chars_bigendian (f
++, insn
->opc
, 1);
2834 number_to_chars_bigendian (f
++, lb
, 1);
2836 emit_15_bit_offset (f
, 4, &exp
);
2841 fail_line_pointer
= input_line_pointer
;
2842 input_line_pointer
= ilp
;
2848 tb_opr_rel (const struct instruction
*insn
)
2850 char *ilp
= input_line_pointer
;
2855 if (!lex_opr (buffer
, &n_bytes
, &exp
, false))
2858 if (!lex_match (','))
2861 bool long_displacement
;
2863 if (! lex_15_bit_offset (&long_displacement
, &exp2
))
2868 if (0 == strncmp (insn
->name
+ 2, "ne", 2))
2870 else if (0 == strncmp (insn
->name
+ 2, "eq", 2))
2872 else if (0 == strncmp (insn
->name
+ 2, "pl", 2))
2874 else if (0 == strncmp (insn
->name
+ 2, "mi", 2))
2876 else if (0 == strncmp (insn
->name
+ 2, "gt", 2))
2878 else if (0 == strncmp (insn
->name
+ 2, "le", 2))
2881 switch (insn
->name
[0])
2893 int size
= size_from_suffix (insn
, 0);
2897 char *f
= s12z_new_insn (n_bytes
+ (long_displacement
? 4 : 3));
2898 number_to_chars_bigendian (f
++, insn
->opc
, 1);
2899 number_to_chars_bigendian (f
++, lb
, 1);
2900 f
= emit_opr (f
, buffer
, n_bytes
, &exp
);
2902 emit_15_bit_offset (f
, n_bytes
+ 4, &exp2
);
2907 fail_line_pointer
= input_line_pointer
;
2908 input_line_pointer
= ilp
;
2916 test_br_reg_reg_rel (const struct instruction
*insn
)
2918 char *ilp
= input_line_pointer
;
2921 if (!lex_reg_name (REG_BIT_Dn
, &Di
))
2924 if (!lex_match (','))
2929 if (!lex_reg_name (REG_BIT_Dn
, &Dn
))
2932 if (!lex_match (','))
2936 bool long_displacement
;
2938 if (! lex_15_bit_offset (&long_displacement
, &exp
))
2947 char *f
= s12z_new_insn (long_displacement
? 5 : 4);
2948 number_to_chars_bigendian (f
++, insn
->opc
, 1);
2949 number_to_chars_bigendian (f
++, bm
, 1);
2950 number_to_chars_bigendian (f
++, xb
, 1);
2952 emit_15_bit_offset (f
, 5, &exp
);
2957 fail_line_pointer
= input_line_pointer
;
2958 input_line_pointer
= ilp
;
2963 test_br_opr_reg_rel (const struct instruction
*insn
)
2965 char *ilp
= input_line_pointer
;
2970 if (!lex_opr (buffer
, &n_bytes
, &exp
, false))
2973 if (!lex_match (','))
2977 if (!lex_reg_name (REG_BIT_Dn
, &Dn
))
2980 if (!lex_match (','))
2985 int size
= size_from_suffix (insn
, 0);
2986 bm
|= (size
-1) << 2;
2988 bool long_displacement
;
2991 if (! lex_15_bit_offset (&long_displacement
, &exp2
))
2994 int n
= n_bytes
+ (long_displacement
? 4 : 3);
2995 char *f
= s12z_new_insn (n
);
2996 number_to_chars_bigendian (f
++, insn
->opc
, 1);
2997 number_to_chars_bigendian (f
++, bm
, 1);
2998 f
= emit_opr (f
, buffer
, n_bytes
, &exp
);
3000 emit_15_bit_offset (f
, n
, &exp2
);
3005 fail_line_pointer
= input_line_pointer
;
3006 input_line_pointer
= ilp
;
3012 test_br_opr_imm_rel (const struct instruction
*insn
)
3014 char *ilp
= input_line_pointer
;
3019 if (!lex_opr (buffer
, &n_bytes
, &exp
, false))
3022 if (!lex_match (','))
3026 if (!lex_imm (&imm
, NULL
))
3029 if (imm
< 0 || imm
> 31)
3032 if (!lex_match (','))
3035 bool long_displacement
;
3037 if (! lex_15_bit_offset (&long_displacement
, &exp2
))
3040 int size
= size_from_suffix (insn
, 0);
3043 bm
|= (imm
& 0x07) << 4;
3044 bm
|= (imm
>> 3) & 0x03;
3050 char *f
= s12z_new_insn (n_bytes
+ (long_displacement
? 4 : 3));
3051 number_to_chars_bigendian (f
++, insn
->opc
, 1);
3052 number_to_chars_bigendian (f
++, bm
, 1);
3053 f
= emit_opr (f
, buffer
, n_bytes
, &exp
);
3055 emit_15_bit_offset (f
, n_bytes
+ 4, &exp2
);
3060 fail_line_pointer
= input_line_pointer
;
3061 input_line_pointer
= ilp
;
3067 test_br_reg_imm_rel (const struct instruction
*insn
)
3069 char *ilp
= input_line_pointer
;
3072 if (!lex_reg_name (REG_BIT_Dn
, &Di
))
3075 if (!lex_match (','))
3079 if (!lex_imm (&imm
, NULL
))
3082 if (imm
< 0 || imm
> 31)
3086 if (!lex_match (','))
3089 bool long_displacement
;
3091 if (! lex_15_bit_offset (&long_displacement
, &exp
))
3097 char *f
= s12z_new_insn (long_displacement
? 4 : 3);
3098 number_to_chars_bigendian (f
++, insn
->opc
, 1);
3099 number_to_chars_bigendian (f
++, bm
, 1);
3101 emit_15_bit_offset (f
, 4, &exp
);
3106 fail_line_pointer
= input_line_pointer
;
3107 input_line_pointer
= ilp
;
3114 static const struct instruction opcodes
[] = {
3115 {"bgnd", 1, 0x00, no_operands
, 0},
3116 {"nop", 1, 0x01, no_operands
, 0},
3118 {"brclr", 1, 0x02, test_br_reg_reg_rel
, 0},
3119 {"brset", 1, 0x03, test_br_reg_reg_rel
, 0},
3121 {"brclr", 1, 0x02, test_br_reg_imm_rel
, 0},
3122 {"brset", 1, 0x03, test_br_reg_imm_rel
, 0},
3124 {"brclr.b", 1, 0x02, test_br_opr_reg_rel
, 0},
3125 {"brclr.w", 1, 0x02, test_br_opr_reg_rel
, 0},
3126 {"brclr.l", 1, 0x02, test_br_opr_reg_rel
, 0},
3128 {"brset.b", 1, 0x03, test_br_opr_reg_rel
, 0},
3129 {"brset.w", 1, 0x03, test_br_opr_reg_rel
, 0},
3130 {"brset.l", 1, 0x03, test_br_opr_reg_rel
, 0},
3132 {"brclr.b", 1, 0x02, test_br_opr_imm_rel
, 0},
3133 {"brclr.w", 1, 0x02, test_br_opr_imm_rel
, 0},
3134 {"brclr.l", 1, 0x02, test_br_opr_imm_rel
, 0},
3136 {"brset.b", 1, 0x03, test_br_opr_imm_rel
, 0},
3137 {"brset.w", 1, 0x03, test_br_opr_imm_rel
, 0},
3138 {"brset.l", 1, 0x03, test_br_opr_imm_rel
, 0},
3140 {"psh", 1, 0x04, psh_pull
, 0},
3141 {"pul", 1, 0x04, psh_pull
, 0},
3143 {"rts", 1, 0x05, no_operands
, 0},
3144 {"lea", 1, 0x06, reg67sxy_opr
, 0},
3146 {"dbne", 1, 0x0b, tb_reg_rel
, 0},
3147 {"dbeq", 1, 0x0b, tb_reg_rel
, 0},
3148 {"dbpl", 1, 0x0b, tb_reg_rel
, 0},
3149 {"dbmi", 1, 0x0b, tb_reg_rel
, 0},
3150 {"dbgt", 1, 0x0b, tb_reg_rel
, 0},
3151 {"dble", 1, 0x0b, tb_reg_rel
, 0},
3153 {"dbne.b", 1, 0x0b, tb_opr_rel
, 0},
3154 {"dbeq.b", 1, 0x0b, tb_opr_rel
, 0},
3155 {"dbpl.b", 1, 0x0b, tb_opr_rel
, 0},
3156 {"dbmi.b", 1, 0x0b, tb_opr_rel
, 0},
3157 {"dbgt.b", 1, 0x0b, tb_opr_rel
, 0},
3158 {"dble.b", 1, 0x0b, tb_opr_rel
, 0},
3160 {"dbne.w", 1, 0x0b, tb_opr_rel
, 0},
3161 {"dbeq.w", 1, 0x0b, tb_opr_rel
, 0},
3162 {"dbpl.w", 1, 0x0b, tb_opr_rel
, 0},
3163 {"dbmi.w", 1, 0x0b, tb_opr_rel
, 0},
3164 {"dbgt.w", 1, 0x0b, tb_opr_rel
, 0},
3165 {"dble.w", 1, 0x0b, tb_opr_rel
, 0},
3167 {"dbne.p", 1, 0x0b, tb_opr_rel
, 0},
3168 {"dbeq.p", 1, 0x0b, tb_opr_rel
, 0},
3169 {"dbpl.p", 1, 0x0b, tb_opr_rel
, 0},
3170 {"dbmi.p", 1, 0x0b, tb_opr_rel
, 0},
3171 {"dbgt.p", 1, 0x0b, tb_opr_rel
, 0},
3172 {"dble.p", 1, 0x0b, tb_opr_rel
, 0},
3174 {"dbne.l", 1, 0x0b, tb_opr_rel
, 0},
3175 {"dbeq.l", 1, 0x0b, tb_opr_rel
, 0},
3176 {"dbpl.l", 1, 0x0b, tb_opr_rel
, 0},
3177 {"dbmi.l", 1, 0x0b, tb_opr_rel
, 0},
3178 {"dbgt.l", 1, 0x0b, tb_opr_rel
, 0},
3179 {"dble.l", 1, 0x0b, tb_opr_rel
, 0},
3181 {"tbne", 1, 0x0b, tb_reg_rel
, 0},
3182 {"tbeq", 1, 0x0b, tb_reg_rel
, 0},
3183 {"tbpl", 1, 0x0b, tb_reg_rel
, 0},
3184 {"tbmi", 1, 0x0b, tb_reg_rel
, 0},
3185 {"tbgt", 1, 0x0b, tb_reg_rel
, 0},
3186 {"tble", 1, 0x0b, tb_reg_rel
, 0},
3188 {"tbne.b", 1, 0x0b, tb_opr_rel
, 0},
3189 {"tbeq.b", 1, 0x0b, tb_opr_rel
, 0},
3190 {"tbpl.b", 1, 0x0b, tb_opr_rel
, 0},
3191 {"tbmi.b", 1, 0x0b, tb_opr_rel
, 0},
3192 {"tbgt.b", 1, 0x0b, tb_opr_rel
, 0},
3193 {"tble.b", 1, 0x0b, tb_opr_rel
, 0},
3195 {"tbne.w", 1, 0x0b, tb_opr_rel
, 0},
3196 {"tbeq.w", 1, 0x0b, tb_opr_rel
, 0},
3197 {"tbpl.w", 1, 0x0b, tb_opr_rel
, 0},
3198 {"tbmi.w", 1, 0x0b, tb_opr_rel
, 0},
3199 {"tbgt.w", 1, 0x0b, tb_opr_rel
, 0},
3200 {"tble.w", 1, 0x0b, tb_opr_rel
, 0},
3202 {"tbne.p", 1, 0x0b, tb_opr_rel
, 0},
3203 {"tbeq.p", 1, 0x0b, tb_opr_rel
, 0},
3204 {"tbpl.p", 1, 0x0b, tb_opr_rel
, 0},
3205 {"tbmi.p", 1, 0x0b, tb_opr_rel
, 0},
3206 {"tbgt.p", 1, 0x0b, tb_opr_rel
, 0},
3207 {"tble.p", 1, 0x0b, tb_opr_rel
, 0},
3209 {"tbne.l", 1, 0x0b, tb_opr_rel
, 0},
3210 {"tbeq.l", 1, 0x0b, tb_opr_rel
, 0},
3211 {"tbpl.l", 1, 0x0b, tb_opr_rel
, 0},
3212 {"tbmi.l", 1, 0x0b, tb_opr_rel
, 0},
3213 {"tbgt.l", 1, 0x0b, tb_opr_rel
, 0},
3214 {"tble.l", 1, 0x0b, tb_opr_rel
, 0},
3216 {"mov.b", 1, 0x0c, imm_opr
, 0},
3217 {"mov.w", 1, 0x0d, imm_opr
, 0},
3218 {"mov.p", 1, 0x0e, imm_opr
, 0},
3219 {"mov.l", 1, 0x0f, imm_opr
, 0},
3221 {"rol", 1, 0x10, rol
, 0},
3222 {"rol.b", 1, 0x10, rol
, 0},
3223 {"rol.w", 1, 0x10, rol
, 0},
3224 {"rol.p", 1, 0x10, rol
, 0},
3225 {"rol.l", 1, 0x10, rol
, 0},
3227 {"ror", 1, 0x10, ror
, 0},
3228 {"ror.b", 1, 0x10, ror
, 0},
3229 {"ror.w", 1, 0x10, ror
, 0},
3230 {"ror.p", 1, 0x10, ror
, 0},
3231 {"ror.l", 1, 0x10, ror
, 0},
3233 {"lsl", 1, 0x10, shift_reg
, 0},
3234 {"lsr", 1, 0x10, shift_reg
, 0},
3235 {"asl", 1, 0x10, shift_reg
, 0},
3236 {"asr", 1, 0x10, shift_reg
, 0},
3238 {"lsl.b", 1, 0x10, shift_two_operand
, 0},
3239 {"lsl.w", 1, 0x10, shift_two_operand
, 0},
3240 {"lsl.p", 1, 0x10, shift_two_operand
, 0},
3241 {"lsl.l", 1, 0x10, shift_two_operand
, 0},
3242 {"asl.b", 1, 0x10, shift_two_operand
, 0},
3243 {"asl.w", 1, 0x10, shift_two_operand
, 0},
3244 {"asl.p", 1, 0x10, shift_two_operand
, 0},
3245 {"asl.l", 1, 0x10, shift_two_operand
, 0},
3247 {"lsr.b", 1, 0x10, shift_two_operand
, 0},
3248 {"lsr.w", 1, 0x10, shift_two_operand
, 0},
3249 {"lsr.p", 1, 0x10, shift_two_operand
, 0},
3250 {"lsr.l", 1, 0x10, shift_two_operand
, 0},
3251 {"asr.b", 1, 0x10, shift_two_operand
, 0},
3252 {"asr.w", 1, 0x10, shift_two_operand
, 0},
3253 {"asr.p", 1, 0x10, shift_two_operand
, 0},
3254 {"asr.l", 1, 0x10, shift_two_operand
, 0},
3256 {"lsl.b", 1, 0x10, shift_opr_imm
, 0},
3257 {"lsl.w", 1, 0x10, shift_opr_imm
, 0},
3258 {"lsl.p", 1, 0x10, shift_opr_imm
, 0},
3259 {"lsl.l", 1, 0x10, shift_opr_imm
, 0},
3260 {"asl.b", 1, 0x10, shift_opr_imm
, 0},
3261 {"asl.w", 1, 0x10, shift_opr_imm
, 0},
3262 {"asl.p", 1, 0x10, shift_opr_imm
, 0},
3263 {"asl.l", 1, 0x10, shift_opr_imm
, 0},
3265 {"lsr.b", 1, 0x10, shift_opr_imm
, 0},
3266 {"lsr.w", 1, 0x10, shift_opr_imm
, 0},
3267 {"lsr.p", 1, 0x10, shift_opr_imm
, 0},
3268 {"lsr.l", 1, 0x10, shift_opr_imm
, 0},
3269 {"asr.b", 1, 0x10, shift_opr_imm
, 0},
3270 {"asr.w", 1, 0x10, shift_opr_imm
, 0},
3271 {"asr.p", 1, 0x10, shift_opr_imm
, 0},
3272 {"asr.l", 1, 0x10, shift_opr_imm
, 0},
3274 {"mov.b", 1, 0x1c, opr_opr
, 0},
3275 {"mov.w", 1, 0x1d, opr_opr
, 0},
3276 {"mov.p", 1, 0x1e, opr_opr
, 0},
3277 {"mov.l", 1, 0x1f, opr_opr
, 0},
3279 {"bra", 1, 0x20, rel
, 0},
3280 {"bsr", 1, 0x21, rel
, 0},
3281 {"bhi", 1, 0x22, rel
, 0},
3282 {"bls", 1, 0x23, rel
, 0},
3283 {"bcc", 1, 0x24, rel
, 0},
3284 {"bhs", 1, 0x24, rel
, 0}, /* Alias for bcc */
3285 {"bcs", 1, 0x25, rel
, 0},
3286 {"blo", 1, 0x25, rel
, 0}, /* Alias for bcs */
3287 {"bne", 1, 0x26, rel
, 0},
3288 {"beq", 1, 0x27, rel
, 0},
3289 {"bvc", 1, 0x28, rel
, 0},
3290 {"bvs", 1, 0x29, rel
, 0},
3291 {"bpl", 1, 0x2a, rel
, 0},
3292 {"bmi", 1, 0x2b, rel
, 0},
3293 {"bge", 1, 0x2c, rel
, 0},
3294 {"blt", 1, 0x2d, rel
, 0},
3295 {"bgt", 1, 0x2e, rel
, 0},
3296 {"ble", 1, 0x2f, rel
, 0},
3298 {"inc", 1, 0x30, reg_inh
, 0},
3299 {"clr", 1, 0x38, reg_inh
, 0},
3300 {"dec", 1, 0x40, reg_inh
, 0},
3302 {"muls", 1, 0x48, mul_reg_reg_reg
, 0},
3303 {"mulu", 1, 0x48, mul_reg_reg_reg
, 0},
3305 {"muls.b", 1, 0x48, mul_reg_reg_opr
, 0},
3306 {"muls.w", 1, 0x48, mul_reg_reg_opr
, 0},
3307 {"muls.l", 1, 0x48, mul_reg_reg_opr
, 0},
3309 {"mulu.b", 1, 0x48, mul_reg_reg_opr
, 0},
3310 {"mulu.w", 1, 0x48, mul_reg_reg_opr
, 0},
3311 {"mulu.l", 1, 0x48, mul_reg_reg_opr
, 0},
3313 {"muls.b", 1, 0x48, mul_reg_reg_imm
, 0},
3314 {"muls.w", 1, 0x48, mul_reg_reg_imm
, 0},
3315 {"muls.l", 1, 0x48, mul_reg_reg_imm
, 0},
3317 {"mulu.b", 1, 0x48, mul_reg_reg_imm
, 0},
3318 {"mulu.w", 1, 0x48, mul_reg_reg_imm
, 0},
3319 {"mulu.l", 1, 0x48, mul_reg_reg_imm
, 0},
3321 {"muls.bb", 1, 0x48, mul_reg_opr_opr
, 0},
3322 {"muls.bw", 1, 0x48, mul_reg_opr_opr
, 0},
3323 {"muls.bp", 1, 0x48, mul_reg_opr_opr
, 0},
3324 {"muls.bl", 1, 0x48, mul_reg_opr_opr
, 0},
3326 {"muls.wb", 1, 0x48, mul_reg_opr_opr
, 0},
3327 {"muls.ww", 1, 0x48, mul_reg_opr_opr
, 0},
3328 {"muls.wp", 1, 0x48, mul_reg_opr_opr
, 0},
3329 {"muls.wl", 1, 0x48, mul_reg_opr_opr
, 0},
3331 {"muls.pb", 1, 0x48, mul_reg_opr_opr
, 0},
3332 {"muls.pw", 1, 0x48, mul_reg_opr_opr
, 0},
3333 {"muls.pp", 1, 0x48, mul_reg_opr_opr
, 0},
3334 {"muls.pl", 1, 0x48, mul_reg_opr_opr
, 0},
3336 {"muls.lb", 1, 0x48, mul_reg_opr_opr
, 0},
3337 {"muls.lw", 1, 0x48, mul_reg_opr_opr
, 0},
3338 {"muls.lp", 1, 0x48, mul_reg_opr_opr
, 0},
3339 {"muls.ll", 1, 0x48, mul_reg_opr_opr
, 0},
3341 {"mulu.bb", 1, 0x48, mul_reg_opr_opr
, 0},
3342 {"mulu.bw", 1, 0x48, mul_reg_opr_opr
, 0},
3343 {"mulu.bp", 1, 0x48, mul_reg_opr_opr
, 0},
3344 {"mulu.bl", 1, 0x48, mul_reg_opr_opr
, 0},
3346 {"mulu.wb", 1, 0x48, mul_reg_opr_opr
, 0},
3347 {"mulu.ww", 1, 0x48, mul_reg_opr_opr
, 0},
3348 {"mulu.wp", 1, 0x48, mul_reg_opr_opr
, 0},
3349 {"mulu.wl", 1, 0x48, mul_reg_opr_opr
, 0},
3351 {"mulu.pb", 1, 0x48, mul_reg_opr_opr
, 0},
3352 {"mulu.pw", 1, 0x48, mul_reg_opr_opr
, 0},
3353 {"mulu.pp", 1, 0x48, mul_reg_opr_opr
, 0},
3354 {"mulu.pl", 1, 0x48, mul_reg_opr_opr
, 0},
3356 {"mulu.lb", 1, 0x48, mul_reg_opr_opr
, 0},
3357 {"mulu.lw", 1, 0x48, mul_reg_opr_opr
, 0},
3358 {"mulu.lp", 1, 0x48, mul_reg_opr_opr
, 0},
3359 {"mulu.ll", 1, 0x48, mul_reg_opr_opr
, 0},
3361 {"add", 1, 0x50, regd_imm
, 0},
3362 {"and", 1, 0x58, regd_imm
, 0},
3364 {"add", 1, 0x60, regd_opr
, 0},
3365 {"and", 1, 0x68, regd_opr
, 0},
3367 {"sub", 1, 0x70, regd_imm
, 0},
3368 {"or", 1, 0x78, regd_imm
, 0},
3370 {"sub", 1, 0x80, regd_opr
, 0},
3371 {"or", 1, 0x88, regd_opr
, 0},
3373 {"ld", 1, 0x90, regdxy_imm
, 0},
3375 {"clr", 1, 0x9a, clr_xy
, 0},
3376 {"tfr", 1, 0x9e, tfr
, 0},
3377 {"zex", 1, 0x9e, tfr
, 0},
3379 {"ld", 1, 0xa0, regdxy_opr_src
, 0xb0},
3381 {"jmp", 1, 0xaa, opr
, 0xba},
3382 {"jsr", 1, 0xab, opr
, 0xbb},
3384 {"exg", 1, 0xae, tfr
, 0},
3385 {"sex", 1, 0xae, tfr
, 0},
3387 {"st", 1, 0xc0, regdxy_opr_dest
, 0xd0},
3389 {"andcc", 1, 0xce, imm8
, 0},
3390 {"orcc", 1, 0xde, imm8
, 0},
3392 {"inc.b", 1, 0x9c, opr
, 0},
3393 {"inc.w", 1, 0x9d, opr
, 0},
3394 {"inc.l", 1, 0x9f, opr
, 0},
3396 {"dec.b", 1, 0xac, opr
, 0},
3397 {"dec.w", 1, 0xad, opr
, 0},
3398 {"dec.l", 1, 0xaf, opr
, 0},
3400 {"clr.b", 1, 0xbc, opr
, 0},
3401 {"clr.w", 1, 0xbd, opr
, 0},
3402 {"clr.p", 1, 0xbe, opr
, 0},
3403 {"clr.l", 1, 0xbf, opr
, 0},
3405 {"com.b", 1, 0xcc, opr
, 0},
3406 {"com.w", 1, 0xcd, opr
, 0},
3407 {"com.l", 1, 0xcf, opr
, 0},
3409 {"neg.b", 1, 0xdc, opr
, 0},
3410 {"neg.w", 1, 0xdd, opr
, 0},
3411 {"neg.l", 1, 0xdf, opr
, 0},
3413 {"bclr", 1, 0xec, bm_regd_imm
, 0},
3414 {"bset", 1, 0xed, bm_regd_imm
, 0},
3415 {"btgl", 1, 0xee, bm_regd_imm
, 0},
3417 {"bclr", 1, 0xec, bm_regd_reg
, 0},
3418 {"bset", 1, 0xed, bm_regd_reg
, 0},
3419 {"btgl", 1, 0xee, bm_regd_reg
, 0},
3421 {"bclr.b", 1, 0xec, bm_opr_imm
, 0},
3422 {"bclr.w", 1, 0xec, bm_opr_imm
, 0},
3423 {"bclr.l", 1, 0xec, bm_opr_imm
, 0},
3425 {"bset.b", 1, 0xed, bm_opr_imm
, 0},
3426 {"bset.w", 1, 0xed, bm_opr_imm
, 0},
3427 {"bset.l", 1, 0xed, bm_opr_imm
, 0},
3429 {"btgl.b", 1, 0xee, bm_opr_imm
, 0},
3430 {"btgl.w", 1, 0xee, bm_opr_imm
, 0},
3431 {"btgl.l", 1, 0xee, bm_opr_imm
, 0},
3433 {"bclr.b", 1, 0xec, bm_opr_reg
, 0},
3434 {"bclr.w", 1, 0xec, bm_opr_reg
, 0},
3435 {"bclr.l", 1, 0xec, bm_opr_reg
, 0},
3437 {"bset.b", 1, 0xed, bm_opr_reg
, 0},
3438 {"bset.w", 1, 0xed, bm_opr_reg
, 0},
3439 {"bset.l", 1, 0xed, bm_opr_reg
, 0},
3441 {"btgl.b", 1, 0xee, bm_opr_reg
, 0},
3442 {"btgl.w", 1, 0xee, bm_opr_reg
, 0},
3443 {"btgl.l", 1, 0xee, bm_opr_reg
, 0},
3445 {"cmp", 1, 0xe0, regdxy_imm
, 0},
3446 {"cmp", 1, 0xf0, regdxy_opr_src
, 0},
3448 {"cmp", 1, 0xfc, regx_regy
, 0},
3449 {"sub", 1, 0xfd, regd6_regx_regy
, 0},
3450 {"sub", 1, 0xfe, regd6_regy_regx
, 0},
3452 {"swi", 1, 0xff, no_operands
, 0},
3456 /* The -10 below is a kludge. The opcode is in fact 0x00 */
3457 {"ld", 2, -10, regs_opr_src
, 0},
3459 /* The -9 below is a kludge. The opcode is in fact 0x01 */
3460 {"st", 2, -9, regs_opr_dest
, 0},
3462 /* The -8 below is a kludge. The opcode is in fact 0x02 */
3463 {"cmp", 2, -8, regs_opr_src
, 0},
3465 /* The -7 below is a kludge. The opcode is in fact 0x03 */
3466 {"ld", 2, -7, regs_imm
, 0},
3468 /* The -6 below is a kludge. The opcode is in fact 0x04 */
3469 {"cmp", 2, -6, regs_imm
, 0},
3471 {"bfext", 2, 0x08, bfe_reg_reg_reg
, 0},
3472 {"bfext", 2, 0x08, bfe_reg_reg_imm
, 0},
3473 {"bfext.b", 2, 0x08, bfe_reg_opr_reg
, 0},
3474 {"bfext.w", 2, 0x08, bfe_reg_opr_reg
, 0},
3475 {"bfext.p", 2, 0x08, bfe_reg_opr_reg
, 0},
3476 {"bfext.l", 2, 0x08, bfe_reg_opr_reg
, 0},
3477 {"bfext.b", 2, 0x08, bfe_opr_reg_reg
, 0},
3478 {"bfext.w", 2, 0x08, bfe_opr_reg_reg
, 0},
3479 {"bfext.p", 2, 0x08, bfe_opr_reg_reg
, 0},
3480 {"bfext.l", 2, 0x08, bfe_opr_reg_reg
, 0},
3481 {"bfext.b", 2, 0x08, bfe_reg_opr_imm
, 0},
3482 {"bfext.w", 2, 0x08, bfe_reg_opr_imm
, 0},
3483 {"bfext.p", 2, 0x08, bfe_reg_opr_imm
, 0},
3484 {"bfext.l", 2, 0x08, bfe_reg_opr_imm
, 0},
3485 {"bfext.b", 2, 0x08, bfe_opr_reg_imm
, 0},
3486 {"bfext.w", 2, 0x08, bfe_opr_reg_imm
, 0},
3487 {"bfext.p", 2, 0x08, bfe_opr_reg_imm
, 0},
3488 {"bfext.l", 2, 0x08, bfe_opr_reg_imm
, 0},
3491 {"bfins", 2, 0x08, bfi_reg_reg_reg
, 0},
3492 {"bfins", 2, 0x08, bfi_reg_reg_imm
, 0},
3493 {"bfins.b", 2, 0x08, bfi_reg_opr_reg
, 0},
3494 {"bfins.w", 2, 0x08, bfi_reg_opr_reg
, 0},
3495 {"bfins.p", 2, 0x08, bfi_reg_opr_reg
, 0},
3496 {"bfins.l", 2, 0x08, bfi_reg_opr_reg
, 0},
3497 {"bfins.b", 2, 0x08, bfi_opr_reg_reg
, 0},
3498 {"bfins.w", 2, 0x08, bfi_opr_reg_reg
, 0},
3499 {"bfins.p", 2, 0x08, bfi_opr_reg_reg
, 0},
3500 {"bfins.l", 2, 0x08, bfi_opr_reg_reg
, 0},
3501 {"bfins.b", 2, 0x08, bfi_reg_opr_imm
, 0},
3502 {"bfins.w", 2, 0x08, bfi_reg_opr_imm
, 0},
3503 {"bfins.p", 2, 0x08, bfi_reg_opr_imm
, 0},
3504 {"bfins.l", 2, 0x08, bfi_reg_opr_imm
, 0},
3505 {"bfins.b", 2, 0x08, bfi_opr_reg_imm
, 0},
3506 {"bfins.w", 2, 0x08, bfi_opr_reg_imm
, 0},
3507 {"bfins.p", 2, 0x08, bfi_opr_reg_imm
, 0},
3508 {"bfins.l", 2, 0x08, bfi_opr_reg_imm
, 0},
3511 {"minu", 2, 0x10, regd_opr
, 0},
3512 {"maxu", 2, 0x18, regd_opr
, 0},
3513 {"mins", 2, 0x20, regd_opr
, 0},
3514 {"maxs", 2, 0x28, regd_opr
, 0},
3516 {"clb", 2, 0x91, tfr
, 0},
3518 {"trap", 2, 0x00, trap_imm
, 0},
3519 {"abs", 2, 0x40, reg_inh
, 0},
3520 {"sat", 2, 0xa0, reg_inh
, 0},
3522 {"rti", 2, 0x90, no_operands
, 0},
3523 {"stop", 2, 0x05, no_operands
, 0},
3524 {"wai", 2, 0x06, no_operands
, 0},
3525 {"sys", 2, 0x07, no_operands
, 0},
3527 {"bit", 2, 0x58, regd_imm
, 0},
3528 {"bit", 2, 0x68, regd_opr
, 0},
3530 {"adc", 2, 0x50, regd_imm
, 0},
3531 {"adc", 2, 0x60, regd_opr
, 0},
3533 {"sbc", 2, 0x70, regd_imm
, 0},
3534 {"eor", 2, 0x78, regd_imm
, 0},
3536 {"sbc", 2, 0x80, regd_opr
, 0},
3537 {"eor", 2, 0x88, regd_opr
, 0},
3539 {"divs", 2, 0x30, mul_reg_reg_reg
, 0},
3540 {"divu", 2, 0x30, mul_reg_reg_reg
, 0},
3542 {"divs.b", 2, 0x30, mul_reg_reg_opr
, 0},
3543 {"divs.w", 2, 0x30, mul_reg_reg_opr
, 0},
3544 {"divs.l", 2, 0x30, mul_reg_reg_opr
, 0},
3546 {"divu.b", 2, 0x30, mul_reg_reg_opr
, 0},
3547 {"divu.w", 2, 0x30, mul_reg_reg_opr
, 0},
3548 {"divu.l", 2, 0x30, mul_reg_reg_opr
, 0},
3550 {"divs.b", 2, 0x30, mul_reg_reg_imm
, 0},
3551 {"divs.w", 2, 0x30, mul_reg_reg_imm
, 0},
3552 {"divs.l", 2, 0x30, mul_reg_reg_imm
, 0},
3554 {"divu.b", 2, 0x30, mul_reg_reg_imm
, 0},
3555 {"divu.w", 2, 0x30, mul_reg_reg_imm
, 0},
3556 {"divu.l", 2, 0x30, mul_reg_reg_imm
, 0},
3558 {"divs.bb", 2, 0x30, mul_reg_opr_opr
, 0},
3559 {"divs.bw", 2, 0x30, mul_reg_opr_opr
, 0},
3560 {"divs.bp", 2, 0x30, mul_reg_opr_opr
, 0},
3561 {"divs.bl", 2, 0x30, mul_reg_opr_opr
, 0},
3563 {"divs.wb", 2, 0x30, mul_reg_opr_opr
, 0},
3564 {"divs.ww", 2, 0x30, mul_reg_opr_opr
, 0},
3565 {"divs.wp", 2, 0x30, mul_reg_opr_opr
, 0},
3566 {"divs.wl", 2, 0x30, mul_reg_opr_opr
, 0},
3568 {"divs.pb", 2, 0x30, mul_reg_opr_opr
, 0},
3569 {"divs.pw", 2, 0x30, mul_reg_opr_opr
, 0},
3570 {"divs.pp", 2, 0x30, mul_reg_opr_opr
, 0},
3571 {"divs.pl", 2, 0x30, mul_reg_opr_opr
, 0},
3573 {"divs.lb", 2, 0x30, mul_reg_opr_opr
, 0},
3574 {"divs.lw", 2, 0x30, mul_reg_opr_opr
, 0},
3575 {"divs.lp", 2, 0x30, mul_reg_opr_opr
, 0},
3576 {"divs.ll", 2, 0x30, mul_reg_opr_opr
, 0},
3578 {"divu.bb", 2, 0x30, mul_reg_opr_opr
, 0},
3579 {"divu.bw", 2, 0x30, mul_reg_opr_opr
, 0},
3580 {"divu.bp", 2, 0x30, mul_reg_opr_opr
, 0},
3581 {"divu.bl", 2, 0x30, mul_reg_opr_opr
, 0},
3583 {"divu.wb", 2, 0x30, mul_reg_opr_opr
, 0},
3584 {"divu.ww", 2, 0x30, mul_reg_opr_opr
, 0},
3585 {"divu.wp", 2, 0x30, mul_reg_opr_opr
, 0},
3586 {"divu.wl", 2, 0x30, mul_reg_opr_opr
, 0},
3588 {"divu.pb", 2, 0x30, mul_reg_opr_opr
, 0},
3589 {"divu.pw", 2, 0x30, mul_reg_opr_opr
, 0},
3590 {"divu.pp", 2, 0x30, mul_reg_opr_opr
, 0},
3591 {"divu.pl", 2, 0x30, mul_reg_opr_opr
, 0},
3593 {"divu.lb", 2, 0x30, mul_reg_opr_opr
, 0},
3594 {"divu.lw", 2, 0x30, mul_reg_opr_opr
, 0},
3595 {"divu.lp", 2, 0x30, mul_reg_opr_opr
, 0},
3596 {"divu.ll", 2, 0x30, mul_reg_opr_opr
, 0},
3600 {"qmuls", 2, 0xb0, mul_reg_reg_reg
, 0},
3601 {"qmulu", 2, 0xb0, mul_reg_reg_reg
, 0},
3603 {"qmuls.b", 2, 0xb0, mul_reg_reg_opr
, 0},
3604 {"qmuls.w", 2, 0xb0, mul_reg_reg_opr
, 0},
3605 {"qmuls.l", 2, 0xb0, mul_reg_reg_opr
, 0},
3607 {"qmulu.b", 2, 0xb0, mul_reg_reg_opr
, 0},
3608 {"qmulu.w", 2, 0xb0, mul_reg_reg_opr
, 0},
3609 {"qmulu.l", 2, 0xb0, mul_reg_reg_opr
, 0},
3611 {"qmuls.b", 2, 0xb0, mul_reg_reg_imm
, 0},
3612 {"qmuls.w", 2, 0xb0, mul_reg_reg_imm
, 0},
3613 {"qmuls.l", 2, 0xb0, mul_reg_reg_imm
, 0},
3615 {"qmulu.b", 2, 0xb0, mul_reg_reg_imm
, 0},
3616 {"qmulu.w", 2, 0xb0, mul_reg_reg_imm
, 0},
3617 {"qmulu.l", 2, 0xb0, mul_reg_reg_imm
, 0},
3619 {"qmuls.bb", 2, 0xb0, mul_reg_opr_opr
, 0},
3620 {"qmuls.bw", 2, 0xb0, mul_reg_opr_opr
, 0},
3621 {"qmuls.bp", 2, 0xb0, mul_reg_opr_opr
, 0},
3622 {"qmuls.bl", 2, 0xb0, mul_reg_opr_opr
, 0},
3624 {"qmuls.wb", 2, 0xb0, mul_reg_opr_opr
, 0},
3625 {"qmuls.ww", 2, 0xb0, mul_reg_opr_opr
, 0},
3626 {"qmuls.wp", 2, 0xb0, mul_reg_opr_opr
, 0},
3627 {"qmuls.wl", 2, 0xb0, mul_reg_opr_opr
, 0},
3629 {"qmuls.pb", 2, 0xb0, mul_reg_opr_opr
, 0},
3630 {"qmuls.pw", 2, 0xb0, mul_reg_opr_opr
, 0},
3631 {"qmuls.pp", 2, 0xb0, mul_reg_opr_opr
, 0},
3632 {"qmuls.pl", 2, 0xb0, mul_reg_opr_opr
, 0},
3634 {"qmuls.lb", 2, 0xb0, mul_reg_opr_opr
, 0},
3635 {"qmuls.lw", 2, 0xb0, mul_reg_opr_opr
, 0},
3636 {"qmuls.lp", 2, 0xb0, mul_reg_opr_opr
, 0},
3637 {"qmuls.ll", 2, 0xb0, mul_reg_opr_opr
, 0},
3639 {"qmulu.bb", 2, 0xb0, mul_reg_opr_opr
, 0},
3640 {"qmulu.bw", 2, 0xb0, mul_reg_opr_opr
, 0},
3641 {"qmulu.bp", 2, 0xb0, mul_reg_opr_opr
, 0},
3642 {"qmulu.bl", 2, 0xb0, mul_reg_opr_opr
, 0},
3644 {"qmulu.wb", 2, 0xb0, mul_reg_opr_opr
, 0},
3645 {"qmulu.ww", 2, 0xb0, mul_reg_opr_opr
, 0},
3646 {"qmulu.wp", 2, 0xb0, mul_reg_opr_opr
, 0},
3647 {"qmulu.wl", 2, 0xb0, mul_reg_opr_opr
, 0},
3649 {"qmulu.pb", 2, 0xb0, mul_reg_opr_opr
, 0},
3650 {"qmulu.pw", 2, 0xb0, mul_reg_opr_opr
, 0},
3651 {"qmulu.pp", 2, 0xb0, mul_reg_opr_opr
, 0},
3652 {"qmulu.pl", 2, 0xb0, mul_reg_opr_opr
, 0},
3654 {"qmulu.lb", 2, 0xb0, mul_reg_opr_opr
, 0},
3655 {"qmulu.lw", 2, 0xb0, mul_reg_opr_opr
, 0},
3656 {"qmulu.lp", 2, 0xb0, mul_reg_opr_opr
, 0},
3657 {"qmulu.ll", 2, 0xb0, mul_reg_opr_opr
, 0},
3662 {"macs", 2, 0x48, mul_reg_reg_reg
, 0},
3663 {"macu", 2, 0x48, mul_reg_reg_reg
, 0},
3665 {"macs.b", 2, 0x48, mul_reg_reg_opr
, 0},
3666 {"macs.w", 2, 0x48, mul_reg_reg_opr
, 0},
3667 {"macs.l", 2, 0x48, mul_reg_reg_opr
, 0},
3669 {"macu.b", 2, 0x48, mul_reg_reg_opr
, 0},
3670 {"macu.w", 2, 0x48, mul_reg_reg_opr
, 0},
3671 {"macu.l", 2, 0x48, mul_reg_reg_opr
, 0},
3673 {"macs.b", 2, 0x48, mul_reg_reg_imm
, 0},
3674 {"macs.w", 2, 0x48, mul_reg_reg_imm
, 0},
3675 {"macs.l", 2, 0x48, mul_reg_reg_imm
, 0},
3677 {"macu.b", 2, 0x48, mul_reg_reg_imm
, 0},
3678 {"macu.w", 2, 0x48, mul_reg_reg_imm
, 0},
3679 {"macu.l", 2, 0x48, mul_reg_reg_imm
, 0},
3681 {"macs.bb", 2, 0x48, mul_reg_opr_opr
, 0},
3682 {"macs.bw", 2, 0x48, mul_reg_opr_opr
, 0},
3683 {"macs.bp", 2, 0x48, mul_reg_opr_opr
, 0},
3684 {"macs.bl", 2, 0x48, mul_reg_opr_opr
, 0},
3686 {"macs.wb", 2, 0x48, mul_reg_opr_opr
, 0},
3687 {"macs.ww", 2, 0x48, mul_reg_opr_opr
, 0},
3688 {"macs.wp", 2, 0x48, mul_reg_opr_opr
, 0},
3689 {"macs.wl", 2, 0x48, mul_reg_opr_opr
, 0},
3691 {"macs.pb", 2, 0x48, mul_reg_opr_opr
, 0},
3692 {"macs.pw", 2, 0x48, mul_reg_opr_opr
, 0},
3693 {"macs.pp", 2, 0x48, mul_reg_opr_opr
, 0},
3694 {"macs.pl", 2, 0x48, mul_reg_opr_opr
, 0},
3696 {"macs.lb", 2, 0x48, mul_reg_opr_opr
, 0},
3697 {"macs.lw", 2, 0x48, mul_reg_opr_opr
, 0},
3698 {"macs.lp", 2, 0x48, mul_reg_opr_opr
, 0},
3699 {"macs.ll", 2, 0x48, mul_reg_opr_opr
, 0},
3701 {"macu.bb", 2, 0x48, mul_reg_opr_opr
, 0},
3702 {"macu.bw", 2, 0x48, mul_reg_opr_opr
, 0},
3703 {"macu.bp", 2, 0x48, mul_reg_opr_opr
, 0},
3704 {"macu.bl", 2, 0x48, mul_reg_opr_opr
, 0},
3706 {"macu.wb", 2, 0x48, mul_reg_opr_opr
, 0},
3707 {"macu.ww", 2, 0x48, mul_reg_opr_opr
, 0},
3708 {"macu.wp", 2, 0x48, mul_reg_opr_opr
, 0},
3709 {"macu.wl", 2, 0x48, mul_reg_opr_opr
, 0},
3711 {"macu.pb", 2, 0x48, mul_reg_opr_opr
, 0},
3712 {"macu.pw", 2, 0x48, mul_reg_opr_opr
, 0},
3713 {"macu.pp", 2, 0x48, mul_reg_opr_opr
, 0},
3714 {"macu.pl", 2, 0x48, mul_reg_opr_opr
, 0},
3716 {"macu.lb", 2, 0x48, mul_reg_opr_opr
, 0},
3717 {"macu.lw", 2, 0x48, mul_reg_opr_opr
, 0},
3718 {"macu.lp", 2, 0x48, mul_reg_opr_opr
, 0},
3719 {"macu.ll", 2, 0x48, mul_reg_opr_opr
, 0},
3724 {"mods", 2, 0x38, mul_reg_reg_reg
, 0},
3725 {"modu", 2, 0x38, mul_reg_reg_reg
, 0},
3727 {"mods.b", 2, 0x38, mul_reg_reg_opr
, 0},
3728 {"mods.w", 2, 0x38, mul_reg_reg_opr
, 0},
3729 {"mods.l", 2, 0x38, mul_reg_reg_opr
, 0},
3731 {"modu.b", 2, 0x38, mul_reg_reg_opr
, 0},
3732 {"modu.w", 2, 0x38, mul_reg_reg_opr
, 0},
3733 {"modu.l", 2, 0x38, mul_reg_reg_opr
, 0},
3735 {"mods.b", 2, 0x38, mul_reg_reg_imm
, 0},
3736 {"mods.w", 2, 0x38, mul_reg_reg_imm
, 0},
3737 {"mods.l", 2, 0x38, mul_reg_reg_imm
, 0},
3739 {"modu.b", 2, 0x38, mul_reg_reg_imm
, 0},
3740 {"modu.w", 2, 0x38, mul_reg_reg_imm
, 0},
3741 {"modu.l", 2, 0x38, mul_reg_reg_imm
, 0},
3743 {"mods.bb", 2, 0x38, mul_reg_opr_opr
, 0},
3744 {"mods.bw", 2, 0x38, mul_reg_opr_opr
, 0},
3745 {"mods.bp", 2, 0x38, mul_reg_opr_opr
, 0},
3746 {"mods.bl", 2, 0x38, mul_reg_opr_opr
, 0},
3748 {"mods.wb", 2, 0x38, mul_reg_opr_opr
, 0},
3749 {"mods.ww", 2, 0x38, mul_reg_opr_opr
, 0},
3750 {"mods.wp", 2, 0x38, mul_reg_opr_opr
, 0},
3751 {"mods.wl", 2, 0x38, mul_reg_opr_opr
, 0},
3753 {"mods.pb", 2, 0x38, mul_reg_opr_opr
, 0},
3754 {"mods.pw", 2, 0x38, mul_reg_opr_opr
, 0},
3755 {"mods.pp", 2, 0x38, mul_reg_opr_opr
, 0},
3756 {"mods.pl", 2, 0x38, mul_reg_opr_opr
, 0},
3758 {"mods.lb", 2, 0x38, mul_reg_opr_opr
, 0},
3759 {"mods.lw", 2, 0x38, mul_reg_opr_opr
, 0},
3760 {"mods.lp", 2, 0x38, mul_reg_opr_opr
, 0},
3761 {"mods.ll", 2, 0x38, mul_reg_opr_opr
, 0},
3763 {"modu.bb", 2, 0x38, mul_reg_opr_opr
, 0},
3764 {"modu.bw", 2, 0x38, mul_reg_opr_opr
, 0},
3765 {"modu.bp", 2, 0x38, mul_reg_opr_opr
, 0},
3766 {"modu.bl", 2, 0x38, mul_reg_opr_opr
, 0},
3768 {"modu.wb", 2, 0x38, mul_reg_opr_opr
, 0},
3769 {"modu.ww", 2, 0x38, mul_reg_opr_opr
, 0},
3770 {"modu.wp", 2, 0x38, mul_reg_opr_opr
, 0},
3771 {"modu.wl", 2, 0x38, mul_reg_opr_opr
, 0},
3773 {"modu.pb", 2, 0x38, mul_reg_opr_opr
, 0},
3774 {"modu.pw", 2, 0x38, mul_reg_opr_opr
, 0},
3775 {"modu.pp", 2, 0x38, mul_reg_opr_opr
, 0},
3776 {"modu.pl", 2, 0x38, mul_reg_opr_opr
, 0},
3778 {"modu.lb", 2, 0x38, mul_reg_opr_opr
, 0},
3779 {"modu.lw", 2, 0x38, mul_reg_opr_opr
, 0},
3780 {"modu.lp", 2, 0x38, mul_reg_opr_opr
, 0},
3781 {"modu.ll", 2, 0x38, mul_reg_opr_opr
, 0}
3785 /* Gas line assembler entry point. */
3787 /* This is the main entry point for the machine-dependent assembler. str
3788 points to a machine-dependent instruction. This function is supposed to
3789 emit the frags/bytes it assembles to. */
3791 md_assemble (char *str
)
3798 fail_line_pointer
= NULL
;
3800 /* Find the opcode end and get the opcode in 'name'. The opcode is forced
3801 lower case (the opcode table only has lower case op-codes). */
3802 for (op_start
= op_end
= str
;
3803 *op_end
&& !is_end_of_line
[(int)*op_end
] && *op_end
!= ' ';
3806 name
[nlen
] = TOLOWER (op_start
[nlen
]);
3808 gas_assert (nlen
< sizeof (name
) - 1);
3814 as_bad (_("No instruction or missing opcode."));
3818 input_line_pointer
= skip_whites (op_end
);
3821 for (i
= 0; i
< sizeof (opcodes
) / sizeof (opcodes
[0]); ++i
)
3823 const struct instruction
*opc
= opcodes
+ i
;
3824 if (0 == strcmp (name
, opc
->name
))
3826 if (opc
->parse_operands (opc
))
3832 as_bad (_("Invalid instruction: \"%s\""), str
);
3833 as_bad (_("First invalid token: \"%s\""), fail_line_pointer
);
3834 while (*input_line_pointer
++)
3842 /* Relocation, relaxation and frag conversions. */
3844 /* PC-relative offsets are relative to the start of the
3845 next instruction. That is, the address of the offset, plus its
3846 size, since the offset is always the last part of the insn. */
3848 md_pcrel_from (fixS
*fixP
)
3850 long ret
= fixP
->fx_size
+ fixP
->fx_frag
->fr_address
;
3851 if (fixP
->fx_addsy
&& S_IS_DEFINED (fixP
->fx_addsy
))
3852 ret
+= fixP
->fx_where
;
3858 /* We need a port-specific relaxation function to cope with sym2 - sym1
3859 relative expressions with both symbols in the same segment (but not
3860 necessarily in the same frag as this insn), for example:
3861 ldab sym2-(sym1-2),pc
3863 The offset can be 5, 9 or 16 bits long. */
3866 s12z_relax_frag (segT seg ATTRIBUTE_UNUSED
, fragS
*fragP ATTRIBUTE_UNUSED
,
3867 long stretch ATTRIBUTE_UNUSED
)
3873 md_convert_frag (bfd
*abfd ATTRIBUTE_UNUSED
, asection
*sec ATTRIBUTE_UNUSED
,
3874 fragS
*fragP ATTRIBUTE_UNUSED
)
3878 /* On an ELF system, we can't relax a weak symbol. The weak symbol
3879 can be overridden at final link time by a non weak symbol. We can
3880 relax externally visible symbol because there is no shared library
3881 and such symbol can't be overridden (unless they are weak). */
3883 /* Force truly undefined symbols to their maximum size, and generally set up
3884 the frag list to be relaxed. */
3886 md_estimate_size_before_relax (fragS
*fragP ATTRIBUTE_UNUSED
, asection
*segment ATTRIBUTE_UNUSED
)
3892 /* If while processing a fixup, a reloc really needs to be created
3893 then it is done here. */
3895 tc_gen_reloc (asection
*section
, fixS
*fixp
)
3897 arelent
*reloc
= XNEW (arelent
);
3898 reloc
->sym_ptr_ptr
= XNEW (asymbol
*);
3899 *reloc
->sym_ptr_ptr
= symbol_get_bfdsym (fixp
->fx_addsy
);
3900 reloc
->address
= fixp
->fx_frag
->fr_address
+ fixp
->fx_where
;
3901 reloc
->howto
= bfd_reloc_type_lookup (stdoutput
, fixp
->fx_r_type
);
3902 if (reloc
->howto
== (reloc_howto_type
*) NULL
)
3904 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
3905 _("Relocation %d is not supported by object file format."),
3906 (int) fixp
->fx_r_type
);
3910 if (0 == (section
->flags
& SEC_CODE
))
3911 reloc
->addend
= fixp
->fx_offset
;
3913 reloc
->addend
= fixp
->fx_addnumber
;
3918 /* See whether we need to force a relocation into the output file. */
3920 tc_s12z_force_relocation (fixS
*fixP
)
3922 return generic_force_reloc (fixP
);
3925 /* Here we decide which fixups can be adjusted to make them relative
3926 to the beginning of the section instead of the symbol. Basically
3927 we need to make sure that the linker relaxation is done
3928 correctly, so in some cases we force the original symbol to be
3931 tc_s12z_fix_adjustable (fixS
*fixP ATTRIBUTE_UNUSED
)
3937 md_apply_fix (fixS
*fixP
, valueT
*valP
, segT seg ATTRIBUTE_UNUSED
)
3941 if (fixP
->fx_addsy
== (symbolS
*) NULL
)
3944 /* We don't actually support subtracting a symbol. */
3945 if (fixP
->fx_subsy
!= (symbolS
*) NULL
)
3946 as_bad_where (fixP
->fx_file
, fixP
->fx_line
, _("Expression too complex."));
3949 Patch the instruction with the resolved operand. Elf relocation
3950 info will also be generated to take care of linker/loader fixups.
3952 char *where
= fixP
->fx_frag
->fr_literal
+ fixP
->fx_where
;
3954 switch (fixP
->fx_r_type
)
3957 ((bfd_byte
*) where
)[0] = (bfd_byte
) value
;
3960 bfd_putb16 ((bfd_vma
) value
, (unsigned char *) where
);
3963 bfd_putb24 ((bfd_vma
) value
, (unsigned char *) where
);
3965 case BFD_RELOC_S12Z_OPR
:
3967 switch (fixP
->fx_size
)
3970 bfd_putb24 ((bfd_vma
) value
, (unsigned char *) where
);
3973 bfd_putb16 ((bfd_vma
) value
, (unsigned char *) where
);
3981 bfd_putb32 ((bfd_vma
) value
, (unsigned char *) where
);
3983 case BFD_RELOC_16_PCREL
:
3984 if (value
< -0x4000 || value
> 0x3FFF)
3985 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
3986 _("Value out of 16-bit range."));
3988 bfd_putb16 ((bfd_vma
) value
| 0x8000, (unsigned char *) where
);
3992 as_fatal (_("Line %d: unknown relocation type: 0x%x."),
3993 fixP
->fx_line
, fixP
->fx_r_type
);
3997 /* Set the ELF specific flags. */
3999 s12z_elf_final_processing (void)