1 /* tc-s12z.c -- Assembler code for the Freescale S12Z
2 Copyright (C) 2018-2019 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 const char EXP_CHARS
[] = "eE";
36 const char FLT_CHARS
[] = "dD";
38 static char *fail_line_pointer
;
41 /* Options and initialization. */
43 const char *md_shortopts
= "Sm:";
45 struct option md_longopts
[] =
49 size_t md_longopts_size
= sizeof (md_longopts
);
52 relax_typeS md_relax_table
[] =
57 /* This table describes all the machine specific pseudo-ops the assembler
58 has to support. The fields are:
59 pseudo-op name without dot
60 function to call to execute this pseudo-op
61 Integer arg to pass to the function. */
62 const pseudo_typeS md_pseudo_table
[] =
68 /* Get the target cpu for the assembler. */
70 s12z_arch_format (void)
87 /* Listing header selected according to cpu. */
89 s12z_listing_header (void)
95 md_show_usage (FILE *stream ATTRIBUTE_UNUSED
)
100 s12z_print_statistics (FILE *file ATTRIBUTE_UNUSED
)
105 md_parse_option (int c ATTRIBUTE_UNUSED
, const char *arg ATTRIBUTE_UNUSED
)
111 md_undefined_symbol (char *name ATTRIBUTE_UNUSED
)
117 md_atof (int type
, char *litP
, int *sizeP
)
119 return ieee_md_atof (type
, litP
, sizeP
, TRUE
);
123 md_section_align (asection
*seg
, valueT addr
)
125 int align
= bfd_get_section_alignment (stdoutput
, seg
);
126 return ((addr
+ (1 << align
) - 1) & -(1 << align
));
135 s12z_init_after_args (void)
143 skip_whites (char *p
)
145 while (*p
== ' ' || *p
== '\t')
153 /* Start a new insn that contains at least 'size' bytes. Record the
154 line information of that insn in the dwarf2 debug sections. */
156 s12z_new_insn (int size
)
158 char *f
= frag_more (size
);
160 dwarf2_emit_insn (size
);
167 static bfd_boolean
lex_reg_name (uint16_t which
, int *reg
);
170 lex_constant (long *v
)
173 char *p
= input_line_pointer
;
175 /* A constant may not have the same value as a register
178 if (lex_reg_name (~0, &dummy
))
180 input_line_pointer
= p
;
185 *v
= strtol (p
, &end
, 0);
186 if (errno
== 0 && end
!= p
)
188 input_line_pointer
= end
;
198 char *p
= input_line_pointer
;
202 input_line_pointer
++;
208 lex_expression (expressionS
*exp
)
210 char *ilp
= input_line_pointer
;
212 exp
->X_op
= O_absent
;
217 if (lex_reg_name (~0, &dummy
))
221 if (exp
->X_op
!= O_absent
)
225 fail_line_pointer
= input_line_pointer
;
226 input_line_pointer
= ilp
;
230 /* Immediate operand.
231 If EXP_O is non-null, then a symbolic expression is permitted,
232 in which case, EXP_O will be populated with the parsed expression.
235 lex_imm (long *v
, expressionS
*exp_o
)
237 char *ilp
= input_line_pointer
;
239 if (*input_line_pointer
!= '#')
242 input_line_pointer
++;
244 if (!lex_expression (&exp
))
247 if (exp
.X_op
!= O_constant
)
250 as_bad (_("A non-constant expression is not permitted here"));
255 *v
= exp
.X_add_number
;
259 fail_line_pointer
= input_line_pointer
;
260 input_line_pointer
= ilp
;
264 /* Short mmediate operand */
266 lex_imm_e4 (long *val
)
268 char *ilp
= input_line_pointer
;
269 if ((lex_imm (val
, NULL
)))
271 if ((*val
== -1) || (*val
> 0 && *val
<= 15))
276 fail_line_pointer
= input_line_pointer
;
277 input_line_pointer
= ilp
;
282 lex_match_string (const char *s
)
284 char *p
= input_line_pointer
;
285 while (p
!= 0 && *p
!= '\t' && *p
!= ' ' && *p
!= '\0')
290 size_t len
= p
- input_line_pointer
;
291 if (len
!= strlen (s
))
294 if (0 == strncasecmp (s
, input_line_pointer
, len
))
296 input_line_pointer
= p
;
303 /* Parse a register name.
304 WHICH is a ORwise combination of the registers which are accepted.
306 On success, REG will be filled with the index of the register which
307 was successfully scanned.
310 lex_reg_name (uint16_t which
, int *reg
)
312 char *p
= input_line_pointer
;
314 ((*p
>= 'a' && *p
<='z') || (*p
>= '0' && *p
<= '9') || (*p
>= 'A' && *p
<='Z')))
319 size_t len
= p
- input_line_pointer
;
325 for (i
= 0; i
< S12Z_N_REGISTERS
; ++i
)
327 gas_assert (registers
[i
].name
);
329 if (len
== strlen (registers
[i
].name
)
330 && 0 == strncasecmp (registers
[i
].name
, input_line_pointer
, len
))
332 if ((0x1U
<< i
) & which
)
334 input_line_pointer
= p
;
345 lex_force_match (char x
)
347 char *p
= input_line_pointer
;
350 as_bad (_("Expecting '%c'"), x
);
354 input_line_pointer
++;
359 lex_opr (uint8_t *buffer
, int *n_bytes
, expressionS
*exp
,
362 char *ilp
= input_line_pointer
;
363 uint8_t *xb
= buffer
;
366 exp
->X_op
= O_absent
;
369 if (lex_imm_e4 (&imm
))
373 as_bad (_("An immediate value in a source operand is inappropriate"));
384 else if (lex_reg_name (REG_BIT_Dn
, ®
))
391 else if (lex_match ('['))
393 if (lex_expression (exp
))
395 long c
= exp
->X_add_number
;
398 if (lex_reg_name (REG_BIT_XYSP
, ®
))
401 if (c
<= 255 && c
>= -256)
411 *xb
|= (reg
- REG_X
) << 4;
415 for (i
= 1; i
< *n_bytes
; ++i
)
417 buffer
[i
] = c
>> (8 * (*n_bytes
- i
- 1));
422 as_bad (_("Bad operand for constant offset"));
435 else if (lex_reg_name (REG_BIT_Dn
, ®
))
437 if (!lex_force_match (','))
441 if (lex_reg_name (REG_BIT_XY
, ®2
))
445 *xb
|= (reg2
- REG_X
) << 4;
450 as_bad (_("Invalid operand for register offset"));
458 if (!lex_force_match (']'))
462 else if (lex_match ('('))
465 if (lex_constant (&c
))
467 if (!lex_force_match (','))
470 if (lex_reg_name (REG_BIT_XYSP
, ®2
))
472 if (reg2
!= REG_P
&& c
>= 0 && c
<= 15)
476 *xb
|= (reg2
- REG_X
) << 4;
479 else if (c
>= -256 && c
<= 255)
483 *xb
|= (reg2
- REG_X
) << 4;
492 *xb
|= (reg2
- REG_X
) << 4;
498 else if (lex_reg_name (REG_BIT_Dn
, ®2
))
500 if (c
>= -1 * (long) (0x1u
<< 17)
502 c
< (long) (0x1u
<< 17) - 1)
507 *xb
|= ((c
>> 16) & 0x03) << 4;
523 as_bad (_("Bad operand for constant offset"));
527 else if (lex_reg_name (REG_BIT_Dn
, ®
))
532 if (lex_reg_name (REG_BIT_XYS
, ®2
))
536 *xb
|= (reg2
- REG_X
) << 4;
541 as_bad (_("Invalid operand for register offset"));
550 else if (lex_reg_name (REG_BIT_XYS
, ®
))
556 as_bad (_("Invalid register for postdecrement operation"));
562 else if (reg
== REG_Y
)
565 else if (lex_match ('+'))
570 else if (reg
== REG_Y
)
572 else if (reg
== REG_S
)
580 else if (lex_match ('+'))
582 if (lex_reg_name (REG_BIT_XY
, ®
))
587 else if (reg
== REG_Y
)
592 as_bad (_("Invalid register for preincrement operation"));
596 else if (lex_match ('-'))
598 if (lex_reg_name (REG_BIT_XYS
, ®
))
603 else if (reg
== REG_Y
)
605 else if (reg
== REG_S
)
610 as_bad (_("Invalid register for predecrement operation"));
619 if (! lex_match (')'))
623 else if (lex_expression (exp
))
630 if (exp
->X_op
== O_constant
)
632 valueT value
= exp
->X_add_number
;
634 if (value
< (0x1U
<< 14))
641 else if (value
< (0x1U
<< 19))
644 if (value
& (0x1U
<< 17))
646 if (value
& (0x1U
<< 16))
649 buffer
[1] = value
>> 8;
656 buffer
[1] = value
>> 16;
657 buffer
[2] = value
>> 8;
665 fail_line_pointer
= input_line_pointer
;
666 input_line_pointer
= ilp
;
671 lex_offset (long *val
)
674 char *p
= input_line_pointer
;
679 if (*p
!= '+' && *p
!= '-')
682 bool negative
= (*p
== '-');
686 *val
= strtol (p
, &end
, 0);
691 input_line_pointer
= end
;
702 typedef int (*parse_operand_func
) (const struct instruction
*);
708 /* The "page" to which the instruction belongs.
709 This is also only a hint. Some instructions might have modes in both
713 /* This is a hint - and only a hint - about the opcode of the instruction.
714 The parse_operand_func is free to ignore it.
718 parse_operand_func parse_operands
;
720 /* Some instructions can be encoded with a different opcode */
725 no_operands (const struct instruction
*insn
)
727 if (*input_line_pointer
!= '\0')
729 as_bad (_("Garbage at end of instruction"));
733 char *f
= s12z_new_insn (insn
->page
);
735 number_to_chars_bigendian (f
++, PAGE2_PREBYTE
, 1);
737 number_to_chars_bigendian (f
++, insn
->opc
, 1);
744 emit_reloc (expressionS
*exp
, char *f
, int size
, enum bfd_reloc_code_real reloc
)
746 if (exp
->X_op
!= O_absent
&& exp
->X_op
!= O_constant
)
748 fixS
*fix
= fix_new_exp (frag_now
,
749 f
- frag_now
->fr_literal
,
754 /* Some third party tools seem to use the lower bits
755 of this addend for flags. They don't get added
756 to the final location. The purpose of these flags
757 is not known. We simply set it to zero. */
758 fix
->fx_addnumber
= 0x00;
762 /* Emit the code for an OPR address mode operand */
764 emit_opr (char *f
, const uint8_t *buffer
, int n_bytes
, expressionS
*exp
)
767 number_to_chars_bigendian (f
++, buffer
[0], 1);
769 emit_reloc (exp
, f
, 3, BFD_RELOC_S12Z_OPR
);
771 for (i
= 1; i
< n_bytes
; ++i
)
772 number_to_chars_bigendian (f
++, buffer
[i
], 1);
777 /* Emit the code for a 24 bit direct address operand */
779 emit_ext24 (char *f
, long v
)
781 number_to_chars_bigendian (f
, v
, 3);
787 opr (const struct instruction
*insn
)
792 if (lex_opr (buffer
, &n_bytes
, &exp
, false))
794 /* Large constant direct values are more efficiently encoded as ext24 mode.
795 Otherwise a decision has to be deferred to a relax. */
796 if (exp
.X_op
== O_constant
798 && insn
->alt_opc
!= 0)
800 char *f
= s12z_new_insn (4);
802 /* I don't think there are any instances of page 2 opcodes in this case */
803 gas_assert (insn
->page
== 1);
805 number_to_chars_bigendian (f
++, insn
->alt_opc
, 1);
807 emit_ext24 (f
, exp
.X_add_number
);
811 char *f
= s12z_new_insn (n_bytes
+ 1);
812 number_to_chars_bigendian (f
++, insn
->opc
, 1);
814 emit_opr (f
, buffer
, n_bytes
, &exp
);
822 /* Parse a 15 bit offset, as an expression.
823 LONG_DISPLACEMENT will be set to true if the offset is wider than 7 bits.
826 lex_15_bit_offset (bool *long_displacement
, expressionS
*exp
)
828 char *ilp
= input_line_pointer
;
831 if (lex_offset (&val
))
833 exp
->X_op
= O_absent
;
834 exp
->X_add_number
= val
;
836 else if (lex_expression (exp
))
838 if (exp
->X_op
== O_constant
)
840 val
= exp
->X_add_number
;
844 /* If a symbol was parsed we don't know the displacement.
845 We have to assume it is long, and relax it later if possible. */
846 *long_displacement
= true;
852 exp
->X_op
= O_absent
;
856 if (val
> 0x3FFF || val
< -0x4000)
858 as_fatal (_("Offset is outside of 15 bit range"));
862 *long_displacement
= (val
> 63 || val
< -64);
867 fail_line_pointer
= input_line_pointer
;
868 input_line_pointer
= ilp
;
873 emit_15_bit_offset (char *f
, int where
, expressionS
*exp
)
876 if (exp
->X_op
!= O_absent
&& exp
->X_op
!= O_constant
)
878 exp
->X_add_number
+= where
;
879 fixS
*fix
= fix_new_exp (frag_now
,
880 f
- frag_now
->fr_literal
,
885 fix
->fx_addnumber
= where
- 2;
889 long val
= exp
->X_add_number
;
890 bool long_displacement
= (val
> 63 || val
< -64);
891 if (long_displacement
)
896 number_to_chars_bigendian (f
++, val
, long_displacement
? 2 : 1);
901 rel (const struct instruction
*insn
)
903 bool long_displacement
;
906 if (! lex_15_bit_offset (&long_displacement
, &exp
))
909 char *f
= s12z_new_insn (long_displacement
? 3 : 2);
910 number_to_chars_bigendian (f
++, insn
->opc
, 1);
911 emit_15_bit_offset (f
, 3, &exp
);
916 reg_inh (const struct instruction
*insn
)
919 if (lex_reg_name (REG_BIT_Dn
, ®
))
921 char *f
= s12z_new_insn (insn
->page
);
923 number_to_chars_bigendian (f
++, PAGE2_PREBYTE
, 1);
925 number_to_chars_bigendian (f
++, insn
->opc
+ reg
, 1);
933 /* Special case for CLR X and CLR Y */
935 clr_xy (const struct instruction
*insn ATTRIBUTE_UNUSED
)
938 if (lex_reg_name (REG_BIT_XY
, ®
))
940 char *f
= s12z_new_insn (1);
941 number_to_chars_bigendian (f
, 0x9a + reg
- REG_X
, 1);
948 /* Some instructions have a suffix like ".l", ".b", ".w" etc
949 which indicates the size of the operands. */
951 size_from_suffix (const struct instruction
*insn
, int idx
)
953 const char *dot
= strchr (insn
->name
, '.');
959 switch (dot
[1 + idx
])
974 as_fatal (_("Bad size"));
981 mul_reg_reg_reg (const struct instruction
*insn
)
983 char *ilp
= input_line_pointer
;
986 if (!lex_reg_name (REG_BIT_Dn
, &Dd
))
989 if (!lex_match (','))
993 if (!lex_reg_name (REG_BIT_Dn
, &Dj
))
996 if (!lex_match (','))
1000 if (!lex_reg_name (REG_BIT_Dn
, &Dk
))
1003 char *f
= s12z_new_insn (insn
->page
+ 1);
1004 if (insn
->page
== 2)
1005 number_to_chars_bigendian (f
++, PAGE2_PREBYTE
, 1);
1007 number_to_chars_bigendian (f
++, insn
->opc
+ Dd
, 1);
1008 const char *dot
= strchrnul (insn
->name
, '.');
1019 as_fatal (_("BAD MUL"));
1026 number_to_chars_bigendian (f
++, mb
, 1);
1031 fail_line_pointer
= input_line_pointer
;
1032 input_line_pointer
= ilp
;
1038 mul_reg_reg_imm (const struct instruction
*insn
)
1040 char *ilp
= input_line_pointer
;
1043 if (!lex_reg_name (REG_BIT_Dn
, &Dd
))
1046 if (!lex_match (','))
1050 if (!lex_reg_name (REG_BIT_Dn
, &Dj
))
1053 if (!lex_match (','))
1057 if (!lex_imm (&imm
, NULL
))
1061 int size
= size_from_suffix (insn
, 0);
1063 char *f
= s12z_new_insn (insn
->page
+ 1 + size
);
1064 if (insn
->page
== 2)
1065 number_to_chars_bigendian (f
++, PAGE2_PREBYTE
, 1);
1067 number_to_chars_bigendian (f
++, insn
->opc
+ Dd
, 1);
1069 const char *dot
= strchrnul (insn
->name
, '.');
1079 as_fatal (_("BAD MUL"));
1086 number_to_chars_bigendian (f
++, mb
, 1);
1087 number_to_chars_bigendian (f
++, imm
, size
);
1092 fail_line_pointer
= input_line_pointer
;
1093 input_line_pointer
= ilp
;
1099 mul_reg_reg_opr (const struct instruction
*insn
)
1101 char *ilp
= input_line_pointer
;
1104 if (!lex_reg_name (REG_BIT_Dn
, &Dd
))
1107 if (!lex_match (','))
1111 if (!lex_reg_name (REG_BIT_Dn
, &Dj
))
1114 if (!lex_match (','))
1120 if (!lex_opr (buffer
, &n_bytes
, &exp
, true))
1123 int size
= size_from_suffix (insn
, 0);
1125 char *f
= s12z_new_insn (insn
->page
+ 1 + n_bytes
);
1126 if (insn
->page
== 2)
1127 number_to_chars_bigendian (f
++, PAGE2_PREBYTE
, 1);
1129 number_to_chars_bigendian (f
++, insn
->opc
+ Dd
, 1);
1131 const char *dot
= strchrnul (insn
->name
, '.');
1141 as_fatal (_("BAD MUL"));
1148 number_to_chars_bigendian (f
++, mb
, 1);
1150 emit_opr (f
, buffer
, n_bytes
, &exp
);
1155 fail_line_pointer
= input_line_pointer
;
1156 input_line_pointer
= ilp
;
1161 mul_reg_opr_opr (const struct instruction
*insn
)
1163 char *ilp
= input_line_pointer
;
1166 if (!lex_reg_name (REG_BIT_Dn
, &Dd
))
1169 if (!lex_match (','))
1175 if (!lex_opr (buffer1
, &n_bytes1
, &exp1
, false))
1178 if (!lex_match (','))
1184 if (!lex_opr (buffer2
, &n_bytes2
, &exp2
, false))
1187 int size1
= size_from_suffix (insn
, 0);
1188 int size2
= size_from_suffix (insn
, 1);
1190 char *f
= s12z_new_insn (insn
->page
+ 1 + n_bytes1
+ n_bytes2
);
1191 if (insn
->page
== 2)
1192 number_to_chars_bigendian (f
++, PAGE2_PREBYTE
, 1);
1194 number_to_chars_bigendian (f
++, insn
->opc
+ Dd
, 1);
1196 const char *dot
= strchrnul (insn
->name
, '.');
1206 as_fatal (_("BAD MUL"));
1210 mb
|= (size1
- 1) << 4;
1211 mb
|= (size2
- 1) << 2;
1212 number_to_chars_bigendian (f
++, mb
, 1);
1214 f
= emit_opr (f
, buffer1
, n_bytes1
, &exp1
);
1215 f
= emit_opr (f
, buffer2
, n_bytes2
, &exp2
);
1220 fail_line_pointer
= input_line_pointer
;
1221 input_line_pointer
= ilp
;
1226 #define REG_BIT_GRP0 \
1227 ((0x1U << REG_D2) | \
1228 (0x1U << REG_D3) | \
1229 (0x1U << REG_CCH) | \
1230 (0x1U << REG_CCL) | \
1231 (0x1U << REG_D0) | \
1234 #define REG_BIT_GRP1 \
1235 ((0x1U << REG_D4) | \
1236 (0x1U << REG_D5) | \
1237 (0x1U << REG_D6) | \
1238 (0x1U << REG_D7) | \
1242 static const uint8_t reg_map
[] =
1262 lex_reg_list (uint16_t grp
, uint16_t *reg_bits
)
1264 if (lex_match (','))
1267 if (!lex_reg_name (grp
, ®
))
1269 *reg_bits
|= 0x1u
<< reg
;
1270 lex_reg_list (grp
, reg_bits
);
1278 psh_pull (const struct instruction
*insn
)
1281 (0 == strcmp ("pul", insn
->name
)) ? 0x80: 0x00;
1283 if (lex_match_string ("all16b"))
1287 else if (lex_match_string ("all"))
1294 if (!lex_reg_name (REG_BIT_GRP1
| REG_BIT_GRP0
, ®1
))
1296 uint16_t admitted_group
= 0;
1298 if ((0x1U
<< reg1
) & REG_BIT_GRP1
)
1299 admitted_group
= REG_BIT_GRP1
;
1300 else if ((0x1U
<< reg1
) & REG_BIT_GRP0
)
1301 admitted_group
= REG_BIT_GRP0
;
1303 uint16_t reg_bits
= 0x1 << reg1
;
1304 if (!lex_reg_list (admitted_group
, ®_bits
))
1307 if (reg_bits
& REG_BIT_GRP1
)
1311 for (i
= 0; i
< 16; ++i
)
1313 if (reg_bits
& (0x1u
<< i
))
1318 char *f
= s12z_new_insn (2);
1319 number_to_chars_bigendian (f
++, insn
->opc
, 1);
1320 number_to_chars_bigendian (f
++, pb
, 1);
1324 fail_line_pointer
= input_line_pointer
;
1330 tfr (const struct instruction
*insn
)
1333 if (!lex_reg_name (~0, ®1
))
1336 if (!lex_match (','))
1340 if (!lex_reg_name (~0, ®2
))
1343 if ( ((0 == strcasecmp ("sex", insn
->name
))
1344 || (0 == strcasecmp ("zex", insn
->name
)))
1345 && (registers
[reg2
].bytes
<= registers
[reg1
].bytes
))
1346 as_warn (_("Source register for %s is no larger than the destination register"),
1348 else if (reg1
== reg2
)
1349 as_warn (_("The destination and source registers are identical"));
1351 char *f
= s12z_new_insn (1 + insn
->page
);
1352 if (insn
->page
== 2)
1353 number_to_chars_bigendian (f
++, PAGE2_PREBYTE
, 1);
1355 number_to_chars_bigendian (f
++, insn
->opc
, 1);
1356 number_to_chars_bigendian (f
++, reg1
<< 4 | reg2
, 1);
1361 fail_line_pointer
= input_line_pointer
;
1366 imm8 (const struct instruction
*insn
)
1369 if (! lex_imm (&imm
, NULL
))
1371 if (imm
> 127 || imm
< -128)
1373 as_bad (_("Immediate value %ld is out of range for instruction %s"),
1377 char *f
= s12z_new_insn (2);
1378 number_to_chars_bigendian (f
++, insn
->opc
, 1);
1379 number_to_chars_bigendian (f
++, imm
, 1);
1385 reg_imm (const struct instruction
*insn
, int allowed_reg
)
1387 char *ilp
= input_line_pointer
;
1389 if (lex_reg_name (allowed_reg
, ®
))
1391 if (!lex_force_match (','))
1394 if (! lex_imm (&imm
, NULL
))
1397 short size
= registers
[reg
].bytes
;
1398 char *f
= s12z_new_insn (insn
->page
+ size
);
1399 if (insn
->page
== 2)
1400 number_to_chars_bigendian (f
++, PAGE2_PREBYTE
, 1);
1402 number_to_chars_bigendian (f
++, insn
->opc
+ reg
, 1);
1403 number_to_chars_bigendian (f
++, imm
, size
);
1408 fail_line_pointer
= input_line_pointer
;
1409 input_line_pointer
= ilp
;
1415 regd_imm (const struct instruction
*insn
)
1417 return reg_imm (insn
, REG_BIT_Dn
);
1421 regdxy_imm (const struct instruction
*insn
)
1423 return reg_imm (insn
, REG_BIT_Dn
| REG_BIT_XY
);
1428 regs_imm (const struct instruction
*insn
)
1430 return reg_imm (insn
, 0x1U
<< REG_S
);
1434 trap_imm (const struct instruction
*insn ATTRIBUTE_UNUSED
)
1437 if (! lex_imm (&imm
, NULL
))
1440 if (imm
< 0x92 || imm
> 0xFF ||
1441 (imm
>= 0xA0 && imm
<= 0xA7) ||
1442 (imm
>= 0xB0 && imm
<= 0xB7))
1444 as_bad (_("trap value %ld is not valid"), imm
);
1449 char *f
= s12z_new_insn (2);
1450 number_to_chars_bigendian (f
++, PAGE2_PREBYTE
, 1);
1451 number_to_chars_bigendian (f
++, imm
& 0xFF, 1);
1458 fail_line_pointer
= input_line_pointer
;
1464 /* Special one byte instruction CMP X, Y */
1466 regx_regy (const struct instruction
*insn
)
1469 if (lex_reg_name (0x1U
<< REG_X
, ®
))
1471 if (lex_force_match (','))
1473 if (lex_reg_name (0x1U
<< REG_Y
, ®
))
1475 char *f
= s12z_new_insn (1);
1476 number_to_chars_bigendian (f
, insn
->opc
, 1);
1484 /* Special one byte instruction SUB D6, X, Y */
1486 regd6_regx_regy (const struct instruction
*insn
)
1488 char *ilp
= input_line_pointer
;
1490 if (!lex_reg_name (0x1U
<< REG_D6
, ®
))
1493 if (!lex_match (','))
1496 if (!lex_reg_name (0x1U
<< REG_X
, ®
))
1499 if (!lex_match (','))
1502 if (!lex_reg_name (0x1U
<< REG_Y
, ®
))
1505 char *f
= s12z_new_insn (1);
1506 number_to_chars_bigendian (f
, insn
->opc
, 1);
1510 fail_line_pointer
= input_line_pointer
;
1511 input_line_pointer
= ilp
;
1515 /* Special one byte instruction SUB D6, Y, X */
1517 regd6_regy_regx (const struct instruction
*insn
)
1519 char *ilp
= input_line_pointer
;
1521 if (!lex_reg_name (0x1U
<< REG_D6
, ®
))
1524 if (!lex_match (','))
1527 if (!lex_reg_name (0x1U
<< REG_Y
, ®
))
1530 if (!lex_match (','))
1533 if (!lex_reg_name (0x1U
<< REG_X
, ®
))
1536 char *f
= s12z_new_insn (1);
1537 number_to_chars_bigendian (f
, insn
->opc
, 1);
1541 fail_line_pointer
= input_line_pointer
;
1542 input_line_pointer
= ilp
;
1547 reg_opr (const struct instruction
*insn
, int allowed_regs
,
1550 char *ilp
= input_line_pointer
;
1552 if (lex_reg_name (allowed_regs
, ®
))
1554 if (!lex_force_match (','))
1560 if (lex_opr (buffer
, &n_bytes
, &exp
, immediate_ok
))
1562 /* Large constant direct values are more efficiently encoded as ext24 mode.
1563 Otherwise a decision has to be deferred to a relax. */
1564 if (exp
.X_op
== O_constant
1565 && buffer
[0] == 0xFA
1566 && insn
->alt_opc
!= 0)
1568 char *f
= s12z_new_insn (4);
1570 /* I don't think there are any instances of page 2 opcodes in this case */
1571 gas_assert (insn
->page
== 1);
1573 number_to_chars_bigendian (f
++, insn
->alt_opc
+ reg
, 1);
1575 emit_ext24 (f
, exp
.X_add_number
);
1579 char *f
= s12z_new_insn (n_bytes
+ insn
->page
);
1581 if (insn
->page
== 2)
1582 number_to_chars_bigendian (f
++, PAGE2_PREBYTE
, 1);
1584 number_to_chars_bigendian (f
++, insn
->opc
+ reg
, 1);
1586 emit_opr (f
, buffer
, n_bytes
, &exp
);
1594 fail_line_pointer
= input_line_pointer
;
1595 input_line_pointer
= ilp
;
1601 regdxy_opr_dest (const struct instruction
*insn
)
1603 return reg_opr (insn
, REG_BIT_Dn
| REG_BIT_XY
, false);
1607 regdxy_opr_src (const struct instruction
*insn
)
1609 return reg_opr (insn
, REG_BIT_Dn
| REG_BIT_XY
, true);
1614 regd_opr (const struct instruction
*insn
)
1616 return reg_opr (insn
, REG_BIT_Dn
, true);
1620 /* OP0: S; OP1: destination OPR */
1622 regs_opr_dest (const struct instruction
*insn
)
1624 return reg_opr (insn
, 0x1U
<< REG_S
, false);
1627 /* OP0: S; OP1: source OPR */
1629 regs_opr_src (const struct instruction
*insn
)
1631 return reg_opr (insn
, 0x1U
<< REG_S
, true);
1635 imm_opr (const struct instruction
*insn
)
1637 char *ilp
= input_line_pointer
;
1640 int size
= size_from_suffix (insn
, 0);
1641 exp0
.X_op
= O_absent
;
1643 /* Note: The ternary expression below means that "MOV.x #symbol,
1644 mem-expr" is accepted when x is a member of {'w', 'p', 'l'} but
1646 The Freescale assembler accepts "MOV.b #symbol, mem-expr" but
1647 produces obviously incorrect code. Since such an instruction
1648 would require an 8-bit reloc (which we don't have) and some
1649 non-optimal kludges in the OPR encoding, it seems sensible that
1650 such instructions should be rejected. */
1651 if (!lex_imm (&imm
, size
> 1 ? &exp0
: NULL
))
1654 if (!lex_match (','))
1660 if (!lex_opr (buffer
, &n_bytes
, &exp1
, false))
1663 char *f
= s12z_new_insn (1 + n_bytes
+ size
);
1664 number_to_chars_bigendian (f
++, insn
->opc
, 1);
1666 emit_reloc (&exp0
, f
, size
, size
== 4 ? BFD_RELOC_32
: BFD_RELOC_S12Z_OPR
);
1669 for (i
= 0; i
< size
; ++i
)
1670 number_to_chars_bigendian (f
++, imm
>> (CHAR_BIT
* (size
- i
- 1)), 1);
1672 emit_opr (f
, buffer
, n_bytes
, &exp1
);
1677 fail_line_pointer
= input_line_pointer
;
1678 input_line_pointer
= ilp
;
1683 opr_opr (const struct instruction
*insn
)
1685 char *ilp
= input_line_pointer
;
1690 if (!lex_opr (buffer1
, &n_bytes1
, &exp1
, false))
1694 if (!lex_match (','))
1700 if (!lex_opr (buffer2
, &n_bytes2
, &exp2
, false))
1703 char *f
= s12z_new_insn (1 + n_bytes1
+ n_bytes2
);
1704 number_to_chars_bigendian (f
++, insn
->opc
, 1);
1706 f
= emit_opr (f
, buffer1
, n_bytes1
, &exp1
);
1707 f
= emit_opr (f
, buffer2
, n_bytes2
, &exp2
);
1712 fail_line_pointer
= input_line_pointer
;
1713 input_line_pointer
= ilp
;
1718 reg67sxy_opr (const struct instruction
*insn
)
1721 if (!lex_reg_name (REG_BIT_XYS
| (0x1U
<< REG_D6
) | (0x1U
<< REG_D7
), ®
))
1724 if (!lex_match (','))
1730 if (!lex_opr (buffer
, &n_bytes
, &exp
, false))
1733 char *f
= s12z_new_insn (1 + n_bytes
);
1734 number_to_chars_bigendian (f
++, insn
->opc
+ reg
- REG_D6
, 1);
1735 emit_opr (f
, buffer
, n_bytes
, &exp
);
1741 rotate (const struct instruction
*insn
, short dir
)
1746 if (lex_opr (buffer
, &n_bytes
, &exp
, false))
1748 char *f
= s12z_new_insn (n_bytes
+ 2);
1749 number_to_chars_bigendian (f
++, insn
->opc
, 1);
1750 int size
= size_from_suffix (insn
, 0);
1757 number_to_chars_bigendian (f
++, sb
, 1);
1758 emit_opr (f
, buffer
, n_bytes
, &exp
);
1767 rol (const struct instruction
*insn
)
1769 return rotate (insn
, 1);
1773 ror (const struct instruction
*insn
)
1775 return rotate (insn
, 0);
1779 /* Shift instruction with a register operand and an immediate #1 or #2
1780 left = 1; right = 0;
1781 logical = 0; arithmetic = 1;
1784 lex_shift_reg_imm1 (const struct instruction
*insn
, short type
, short dir
)
1787 This function is highly unusual and a bit wierd!
1788 It first matches the input against a register {d0, d1, ... d7} followed by an immediate
1790 Then, it rewinds the input and parses it again as a OPR.
1792 char *ilp
= input_line_pointer
;
1795 if (!lex_reg_name (REG_BIT_Dn
, &Dd
))
1800 if (!lex_match (','))
1804 if (!lex_imm (&imm
, NULL
))
1807 if (imm
!= 1 && imm
!= 2)
1809 input_line_pointer
= ilp
;
1811 /* Now parse the first operand again */
1817 if (!lex_opr (buffer
, &n_bytes
, &exp
, false))
1820 gas_assert (n_bytes
== 1);
1828 char *f
= s12z_new_insn (3);
1829 number_to_chars_bigendian (f
++, insn
->opc
, 1);
1830 number_to_chars_bigendian (f
++, sb
, 1);
1831 emit_opr (f
, buffer
, n_bytes
, &exp
);
1836 fail_line_pointer
= input_line_pointer
;
1837 input_line_pointer
= ilp
;
1841 /* Shift instruction with a register operand.
1842 left = 1; right = 0;
1843 logical = 0; arithmetic = 1; */
1845 lex_shift_reg (const struct instruction
*insn
, short type
, short dir
)
1848 if (!lex_reg_name (REG_BIT_Dn
, &Dd
))
1853 if (!lex_match (','))
1856 if (!lex_reg_name (REG_BIT_Dn
, &Ds
))
1861 if (!lex_match (','))
1869 if (lex_reg_name (REG_BIT_Dn
, &Dn
))
1871 char *f
= s12z_new_insn (3);
1872 number_to_chars_bigendian (f
++, insn
->opc
| Dd
, 1);
1873 number_to_chars_bigendian (f
++, sb
, 1);
1876 number_to_chars_bigendian (f
++, xb
, 1);
1880 else if (lex_imm (&imm
, NULL
))
1882 if (imm
< 0 || imm
> 31)
1884 as_bad (_("Shift value should be in the range [0,31]"));
1889 if (imm
== 1 || imm
== 2)
1896 sb
|= (imm
& 0x01) << 3;
1899 char *f
= s12z_new_insn (n_bytes
);
1900 number_to_chars_bigendian (f
++, insn
->opc
| Dd
, 1);
1901 number_to_chars_bigendian (f
++, sb
, 1);
1906 number_to_chars_bigendian (f
++, xb
, 1);
1913 fail_line_pointer
= input_line_pointer
;
1918 impute_shift_dir_and_type (const struct instruction
*insn
, short *type
, short *dir
)
1922 switch (insn
->name
[0])
1931 as_fatal (_("Bad shift mode"));
1935 switch (insn
->name
[2])
1944 as_fatal (_("Bad shift *direction"));
1949 /* Shift instruction with a OPR operand */
1951 shift_two_operand (const struct instruction
*insn
)
1954 char *ilp
= input_line_pointer
;
1958 impute_shift_dir_and_type (insn
, &type
, &dir
);
1962 int size
= size_from_suffix (insn
, 0);
1968 if (!lex_opr (buffer
, &n_opr_bytes
, &exp
, false))
1971 if (!lex_match (','))
1975 if (!lex_imm (&imm
, NULL
))
1978 if (imm
!= 1 && imm
!= 2)
1984 char *f
= s12z_new_insn (2 + n_opr_bytes
);
1985 number_to_chars_bigendian (f
++, insn
->opc
, 1);
1986 number_to_chars_bigendian (f
++, sb
, 1);
1987 emit_opr (f
, buffer
, n_opr_bytes
, &exp
);
1992 fail_line_pointer
= input_line_pointer
;
1993 input_line_pointer
= ilp
;
1997 /* Shift instruction with a OPR operand */
1999 shift_opr_imm (const struct instruction
*insn
)
2001 char *ilp
= input_line_pointer
;
2005 impute_shift_dir_and_type (insn
, &type
, &dir
);
2008 if (!lex_reg_name (REG_BIT_Dn
, &Dd
))
2011 if (!lex_match (','))
2020 if (!lex_opr (buffer1
, &n_opr_bytes1
, &exp1
, false))
2023 n_bytes
+= n_opr_bytes1
;
2024 if (!lex_match (','))
2028 int n_opr_bytes2
= 0;
2031 bool immediate
= false;
2032 if (lex_imm (&imm
, NULL
))
2036 else if (!lex_opr (buffer2
, &n_opr_bytes2
, &exp2
, false))
2041 int size
= size_from_suffix (insn
, 0);
2051 if (imm
== 2 || imm
== 1)
2066 n_bytes
+= n_opr_bytes2
;
2070 char *f
= s12z_new_insn (n_bytes
);
2071 number_to_chars_bigendian (f
++, insn
->opc
| Dd
, 1);
2072 number_to_chars_bigendian (f
++, sb
, 1);
2073 f
= emit_opr (f
, buffer1
, n_opr_bytes1
, &exp1
);
2076 if (imm
!= 1 && imm
!= 2)
2078 number_to_chars_bigendian (f
++, 0x70 | (imm
>> 1), 1);
2083 f
= emit_opr (f
, buffer2
, n_opr_bytes2
, &exp2
);
2089 fail_line_pointer
= input_line_pointer
;
2090 input_line_pointer
= ilp
;
2094 /* Shift instruction with a register operand */
2096 shift_reg (const struct instruction
*insn
)
2100 impute_shift_dir_and_type (insn
, &type
, &dir
);
2102 if (lex_shift_reg_imm1 (insn
, type
, dir
))
2105 return lex_shift_reg (insn
, type
, dir
);
2109 bm_regd_imm (const struct instruction
*insn
)
2111 char *ilp
= input_line_pointer
;
2113 if (!lex_reg_name (REG_BIT_Dn
, &Di
))
2116 if (!lex_match (','))
2120 if (!lex_imm (&imm
, NULL
))
2124 uint8_t bm
= imm
<< 3;
2127 char *f
= s12z_new_insn (2);
2128 number_to_chars_bigendian (f
++, insn
->opc
, 1);
2129 number_to_chars_bigendian (f
++, bm
, 1);
2134 fail_line_pointer
= input_line_pointer
;
2135 input_line_pointer
= ilp
;
2140 bm_opr_reg (const struct instruction
*insn
)
2142 char *ilp
= input_line_pointer
;
2148 if (!lex_opr (buffer
, &n_opr_bytes
, &exp
, false))
2151 if (!lex_match (','))
2155 if (!lex_reg_name (REG_BIT_Dn
, &Dn
))
2158 uint8_t bm
= Dn
<< 4;
2159 int size
= size_from_suffix (insn
, 0);
2160 bm
|= (size
- 1) << 2;
2163 char *f
= s12z_new_insn (2 + n_opr_bytes
);
2164 number_to_chars_bigendian (f
++, insn
->opc
, 1);
2165 number_to_chars_bigendian (f
++, bm
, 1);
2167 emit_opr (f
, buffer
, n_opr_bytes
, &exp
);
2172 fail_line_pointer
= input_line_pointer
;
2173 input_line_pointer
= ilp
;
2179 bm_opr_imm (const struct instruction
*insn
)
2181 char *ilp
= input_line_pointer
;
2187 if (!lex_opr (buffer
, &n_opr_bytes
, &exp
, false))
2190 if (!lex_match (','))
2195 if (!lex_imm (&imm
, NULL
))
2198 int size
= size_from_suffix (insn
, 0);
2200 if (imm
< 0 || imm
>= size
* 8)
2202 as_bad (_("Immediate operand %ld is inappropriate for size of instruction"), imm
);
2211 bm
|= (imm
& 0x07) << 4;
2215 char *f
= s12z_new_insn (2 + n_opr_bytes
);
2216 number_to_chars_bigendian (f
++, insn
->opc
, 1);
2217 number_to_chars_bigendian (f
++, bm
, 1);
2218 emit_opr (f
, buffer
, n_opr_bytes
, &exp
);
2223 fail_line_pointer
= input_line_pointer
;
2224 input_line_pointer
= ilp
;
2230 bm_regd_reg (const struct instruction
*insn
)
2232 char *ilp
= input_line_pointer
;
2234 if (!lex_reg_name (REG_BIT_Dn
, &Di
))
2237 if (!lex_match (','))
2241 if (!lex_reg_name (REG_BIT_Dn
, &Dn
))
2244 uint8_t bm
= Dn
<< 4;
2247 uint8_t xb
= Di
| 0xb8;
2249 char *f
= s12z_new_insn (3);
2250 number_to_chars_bigendian (f
++, insn
->opc
, 1);
2251 number_to_chars_bigendian (f
++, bm
, 1);
2252 number_to_chars_bigendian (f
++, xb
, 1);
2257 fail_line_pointer
= input_line_pointer
;
2258 input_line_pointer
= ilp
;
2267 bf_reg_opr_imm (const struct instruction
*insn
, short ie
)
2269 char *ilp
= input_line_pointer
;
2271 if (!lex_reg_name (REG_BIT_Dn
, &Dd
))
2274 if (!lex_match (','))
2281 if (!lex_opr (buffer
, &n_bytes
, &exp
, false))
2284 if (!lex_match (','))
2288 if (!lex_imm (&width
, NULL
))
2291 if (width
< 0 || width
> 31)
2293 as_bad (_("Invalid width value for %s"), insn
->name
);
2297 if (!lex_match (':'))
2301 if (!lex_constant (&offset
))
2304 if (offset
< 0 || offset
> 31)
2306 as_bad (_("Invalid offset value for %s"), insn
->name
);
2310 uint8_t i1
= width
<< 5;
2313 int size
= size_from_suffix (insn
, 0);
2314 uint8_t bb
= ie
? 0x80 : 0x00;
2316 bb
|= (size
- 1) << 2;
2319 char *f
= s12z_new_insn (4 + n_bytes
);
2320 number_to_chars_bigendian (f
++, PAGE2_PREBYTE
, 1);
2321 number_to_chars_bigendian (f
++, 0x08 | Dd
, 1);
2322 number_to_chars_bigendian (f
++, bb
, 1);
2323 number_to_chars_bigendian (f
++, i1
, 1);
2325 emit_opr (f
, buffer
, n_bytes
, &exp
);
2330 fail_line_pointer
= input_line_pointer
;
2331 input_line_pointer
= ilp
;
2337 bf_opr_reg_imm (const struct instruction
*insn
, short ie
)
2339 char *ilp
= input_line_pointer
;
2343 if (!lex_opr (buffer
, &n_bytes
, &exp
, false))
2346 if (!lex_match (','))
2350 if (!lex_reg_name (REG_BIT_Dn
, &Ds
))
2353 if (!lex_match (','))
2357 if (!lex_imm (&width
, NULL
))
2360 if (width
< 0 || width
> 31)
2362 as_bad (_("Invalid width value for %s"), insn
->name
);
2366 if (!lex_match (':'))
2370 if (!lex_constant (&offset
))
2373 if (offset
< 0 || offset
> 31)
2375 as_bad (_("Invalid offset value for %s"), insn
->name
);
2379 uint8_t i1
= width
<< 5;
2382 int size
= size_from_suffix (insn
, 0);
2383 uint8_t bb
= ie
? 0x80 : 0x00;
2385 bb
|= (size
- 1) << 2;
2388 char *f
= s12z_new_insn (4 + n_bytes
);
2389 number_to_chars_bigendian (f
++, PAGE2_PREBYTE
, 1);
2390 number_to_chars_bigendian (f
++, 0x08 | Ds
, 1);
2391 number_to_chars_bigendian (f
++, bb
, 1);
2392 number_to_chars_bigendian (f
++, i1
, 1);
2394 emit_opr (f
, buffer
, n_bytes
, &exp
);
2399 fail_line_pointer
= input_line_pointer
;
2400 input_line_pointer
= ilp
;
2407 bf_reg_reg_imm (const struct instruction
*insn
, short ie
)
2409 char *ilp
= input_line_pointer
;
2411 if (!lex_reg_name (REG_BIT_Dn
, &Dd
))
2414 if (!lex_match (','))
2418 if (!lex_reg_name (REG_BIT_Dn
, &Ds
))
2421 if (!lex_match (','))
2425 if (!lex_imm (&width
, NULL
))
2428 if (width
< 0 || width
> 31)
2430 as_bad (_("Invalid width value for %s"), insn
->name
);
2434 if (!lex_match (':'))
2438 if (!lex_constant (&offset
))
2441 if (offset
< 0 || offset
> 31)
2443 as_bad (_("Invalid offset value for %s"), insn
->name
);
2447 uint8_t bb
= ie
? 0x80 : 0x00;
2452 uint8_t i1
= width
<< 5;
2455 char *f
= s12z_new_insn (4);
2456 number_to_chars_bigendian (f
++, PAGE2_PREBYTE
, 1);
2457 number_to_chars_bigendian (f
++, 0x08 | Dd
, 1);
2458 number_to_chars_bigendian (f
++, bb
, 1);
2459 number_to_chars_bigendian (f
++, i1
, 1);
2464 fail_line_pointer
= input_line_pointer
;
2465 input_line_pointer
= ilp
;
2470 bf_reg_reg_reg (const struct instruction
*insn ATTRIBUTE_UNUSED
, short ie
)
2472 char *ilp
= input_line_pointer
;
2474 if (!lex_reg_name (REG_BIT_Dn
, &Dd
))
2477 if (!lex_match (','))
2481 if (!lex_reg_name (REG_BIT_Dn
, &Ds
))
2484 if (!lex_match (','))
2488 if (!lex_reg_name ((0x01u
<< REG_D2
) |
2495 uint8_t bb
= ie
? 0x80 : 0x00;
2499 char *f
= s12z_new_insn (3);
2500 number_to_chars_bigendian (f
++, PAGE2_PREBYTE
, 1);
2501 number_to_chars_bigendian (f
++, 0x08 | Dd
, 1);
2502 number_to_chars_bigendian (f
++, bb
, 1);
2507 fail_line_pointer
= input_line_pointer
;
2508 input_line_pointer
= ilp
;
2513 bf_opr_reg_reg (const struct instruction
*insn
, short ie
)
2515 char *ilp
= input_line_pointer
;
2520 if (!lex_opr (buffer
, &n_bytes
, &exp
, false))
2523 if (!lex_match (','))
2528 if (!lex_reg_name (REG_BIT_Dn
, &Ds
))
2531 if (!lex_match (','))
2536 if (!lex_reg_name ((0x01u
<< REG_D2
) |
2543 int size
= size_from_suffix (insn
, 0);
2544 uint8_t bb
= ie
? 0x80 : 0x00;
2547 bb
|= (size
- 1) << 2;
2549 char *f
= s12z_new_insn (3 + n_bytes
);
2550 number_to_chars_bigendian (f
++, PAGE2_PREBYTE
, 1);
2551 number_to_chars_bigendian (f
++, 0x08 | Ds
, 1);
2552 number_to_chars_bigendian (f
++, bb
, 1);
2554 emit_opr (f
, buffer
, n_bytes
, &exp
);
2559 fail_line_pointer
= input_line_pointer
;
2560 input_line_pointer
= ilp
;
2566 bf_reg_opr_reg (const struct instruction
*insn
, short ie
)
2568 char *ilp
= input_line_pointer
;
2570 if (!lex_reg_name (REG_BIT_Dn
, &Dd
))
2573 if (!lex_match (','))
2580 if (!lex_opr (buffer
, &n_bytes
, &exp
, false))
2583 if (!lex_match (','))
2587 if (!lex_reg_name ((0x01u
<< REG_D2
) |
2594 int size
= size_from_suffix (insn
, 0);
2595 uint8_t bb
= ie
? 0x80 : 0x00;
2598 bb
|= (size
- 1) << 2;
2600 char *f
= s12z_new_insn (3 + n_bytes
);
2601 number_to_chars_bigendian (f
++, PAGE2_PREBYTE
, 1);
2602 number_to_chars_bigendian (f
++, 0x08 | Dd
, 1);
2603 number_to_chars_bigendian (f
++, bb
, 1);
2605 emit_opr (f
, buffer
, n_bytes
, &exp
);
2610 fail_line_pointer
= input_line_pointer
;
2611 input_line_pointer
= ilp
;
2618 bfe_reg_reg_reg (const struct instruction
*insn
)
2620 return bf_reg_reg_reg (insn
, 0);
2624 bfi_reg_reg_reg (const struct instruction
*insn
)
2626 return bf_reg_reg_reg (insn
, 1);
2630 bfe_reg_reg_imm (const struct instruction
*insn
)
2632 return bf_reg_reg_imm (insn
, 0);
2636 bfi_reg_reg_imm (const struct instruction
*insn
)
2638 return bf_reg_reg_imm (insn
, 1);
2643 bfe_reg_opr_reg (const struct instruction
*insn
)
2645 return bf_reg_opr_reg (insn
, 0);
2649 bfi_reg_opr_reg (const struct instruction
*insn
)
2651 return bf_reg_opr_reg (insn
, 1);
2656 bfe_opr_reg_reg (const struct instruction
*insn
)
2658 return bf_opr_reg_reg (insn
, 0);
2662 bfi_opr_reg_reg (const struct instruction
*insn
)
2664 return bf_opr_reg_reg (insn
, 1);
2668 bfe_reg_opr_imm (const struct instruction
*insn
)
2670 return bf_reg_opr_imm (insn
, 0);
2674 bfi_reg_opr_imm (const struct instruction
*insn
)
2676 return bf_reg_opr_imm (insn
, 1);
2680 bfe_opr_reg_imm (const struct instruction
*insn
)
2682 return bf_opr_reg_imm (insn
, 0);
2686 bfi_opr_reg_imm (const struct instruction
*insn
)
2688 return bf_opr_reg_imm (insn
, 1);
2695 tb_reg_rel (const struct instruction
*insn
)
2697 char *ilp
= input_line_pointer
;
2700 if (!lex_reg_name (REG_BIT_Dn
| REG_BIT_XY
, ®
))
2703 if (!lex_match (','))
2706 bool long_displacement
;
2708 if (! lex_15_bit_offset (&long_displacement
, &exp
))
2712 if (reg
== REG_X
|| reg
== REG_Y
)
2723 if (0 == strncmp (insn
->name
+ 2, "ne", 2))
2725 else if (0 == strncmp (insn
->name
+ 2, "eq", 2))
2727 else if (0 == strncmp (insn
->name
+ 2, "pl", 2))
2729 else if (0 == strncmp (insn
->name
+ 2, "mi", 2))
2731 else if (0 == strncmp (insn
->name
+ 2, "gt", 2))
2733 else if (0 == strncmp (insn
->name
+ 2, "le", 2))
2736 switch (insn
->name
[0])
2748 char *f
= s12z_new_insn (long_displacement
? 4 : 3);
2749 number_to_chars_bigendian (f
++, insn
->opc
, 1);
2750 number_to_chars_bigendian (f
++, lb
, 1);
2752 emit_15_bit_offset (f
, 4, &exp
);
2757 fail_line_pointer
= input_line_pointer
;
2758 input_line_pointer
= ilp
;
2764 tb_opr_rel (const struct instruction
*insn
)
2766 char *ilp
= input_line_pointer
;
2771 if (!lex_opr (buffer
, &n_bytes
, &exp
, false))
2774 if (!lex_match (','))
2777 bool long_displacement
;
2779 if (! lex_15_bit_offset (&long_displacement
, &exp2
))
2784 if (0 == strncmp (insn
->name
+ 2, "ne", 2))
2786 else if (0 == strncmp (insn
->name
+ 2, "eq", 2))
2788 else if (0 == strncmp (insn
->name
+ 2, "pl", 2))
2790 else if (0 == strncmp (insn
->name
+ 2, "mi", 2))
2792 else if (0 == strncmp (insn
->name
+ 2, "gt", 2))
2794 else if (0 == strncmp (insn
->name
+ 2, "le", 2))
2797 switch (insn
->name
[0])
2809 int size
= size_from_suffix (insn
, 0);
2813 char *f
= s12z_new_insn (n_bytes
+ (long_displacement
? 4 : 3));
2814 number_to_chars_bigendian (f
++, insn
->opc
, 1);
2815 number_to_chars_bigendian (f
++, lb
, 1);
2816 f
= emit_opr (f
, buffer
, n_bytes
, &exp
);
2818 emit_15_bit_offset (f
, n_bytes
+ 4, &exp2
);
2823 fail_line_pointer
= input_line_pointer
;
2824 input_line_pointer
= ilp
;
2832 test_br_reg_reg_rel (const struct instruction
*insn
)
2834 char *ilp
= input_line_pointer
;
2837 if (!lex_reg_name (REG_BIT_Dn
, &Di
))
2840 if (!lex_match (','))
2845 if (!lex_reg_name (REG_BIT_Dn
, &Dn
))
2848 if (!lex_match (','))
2852 bool long_displacement
;
2854 if (! lex_15_bit_offset (&long_displacement
, &exp
))
2863 char *f
= s12z_new_insn (long_displacement
? 5 : 4);
2864 number_to_chars_bigendian (f
++, insn
->opc
, 1);
2865 number_to_chars_bigendian (f
++, bm
, 1);
2866 number_to_chars_bigendian (f
++, xb
, 1);
2868 emit_15_bit_offset (f
, 5, &exp
);
2873 fail_line_pointer
= input_line_pointer
;
2874 input_line_pointer
= ilp
;
2879 test_br_opr_reg_rel (const struct instruction
*insn
)
2881 char *ilp
= input_line_pointer
;
2886 if (!lex_opr (buffer
, &n_bytes
, &exp
, false))
2889 if (!lex_match (','))
2893 if (!lex_reg_name (REG_BIT_Dn
, &Dn
))
2896 if (!lex_match (','))
2901 int size
= size_from_suffix (insn
, 0);
2902 bm
|= (size
-1) << 2;
2904 bool long_displacement
;
2907 if (! lex_15_bit_offset (&long_displacement
, &exp2
))
2910 int n
= n_bytes
+ (long_displacement
? 4 : 3);
2911 char *f
= s12z_new_insn (n
);
2912 number_to_chars_bigendian (f
++, insn
->opc
, 1);
2913 number_to_chars_bigendian (f
++, bm
, 1);
2914 f
= emit_opr (f
, buffer
, n_bytes
, &exp
);
2916 emit_15_bit_offset (f
, n
, &exp2
);
2921 fail_line_pointer
= input_line_pointer
;
2922 input_line_pointer
= ilp
;
2928 test_br_opr_imm_rel (const struct instruction
*insn
)
2930 char *ilp
= input_line_pointer
;
2935 if (!lex_opr (buffer
, &n_bytes
, &exp
, false))
2938 if (!lex_match (','))
2942 if (!lex_imm (&imm
, NULL
))
2945 if (imm
< 0 || imm
> 31)
2948 if (!lex_match (','))
2951 bool long_displacement
;
2953 if (! lex_15_bit_offset (&long_displacement
, &exp2
))
2956 int size
= size_from_suffix (insn
, 0);
2959 bm
|= (imm
& 0x07) << 4;
2960 bm
|= (imm
>> 3) & 0x03;
2966 char *f
= s12z_new_insn (n_bytes
+ (long_displacement
? 4 : 3));
2967 number_to_chars_bigendian (f
++, insn
->opc
, 1);
2968 number_to_chars_bigendian (f
++, bm
, 1);
2969 f
= emit_opr (f
, buffer
, n_bytes
, &exp
);
2971 emit_15_bit_offset (f
, n_bytes
+ 4, &exp2
);
2976 fail_line_pointer
= input_line_pointer
;
2977 input_line_pointer
= ilp
;
2983 test_br_reg_imm_rel (const struct instruction
*insn
)
2985 char *ilp
= input_line_pointer
;
2988 if (!lex_reg_name (REG_BIT_Dn
, &Di
))
2991 if (!lex_match (','))
2995 if (!lex_imm (&imm
, NULL
))
2998 if (imm
< 0 || imm
> 31)
3002 if (!lex_match (','))
3005 bool long_displacement
;
3007 if (! lex_15_bit_offset (&long_displacement
, &exp
))
3013 char *f
= s12z_new_insn (long_displacement
? 4 : 3);
3014 number_to_chars_bigendian (f
++, insn
->opc
, 1);
3015 number_to_chars_bigendian (f
++, bm
, 1);
3017 emit_15_bit_offset (f
, 4, &exp
);
3022 fail_line_pointer
= input_line_pointer
;
3023 input_line_pointer
= ilp
;
3030 static const struct instruction opcodes
[] = {
3031 {"bgnd", 1, 0x00, no_operands
, 0},
3032 {"nop", 1, 0x01, no_operands
, 0},
3034 {"brclr", 1, 0x02, test_br_reg_reg_rel
, 0},
3035 {"brset", 1, 0x03, test_br_reg_reg_rel
, 0},
3037 {"brclr", 1, 0x02, test_br_reg_imm_rel
, 0},
3038 {"brset", 1, 0x03, test_br_reg_imm_rel
, 0},
3040 {"brclr.b", 1, 0x02, test_br_opr_reg_rel
, 0},
3041 {"brclr.w", 1, 0x02, test_br_opr_reg_rel
, 0},
3042 {"brclr.l", 1, 0x02, test_br_opr_reg_rel
, 0},
3044 {"brset.b", 1, 0x03, test_br_opr_reg_rel
, 0},
3045 {"brset.w", 1, 0x03, test_br_opr_reg_rel
, 0},
3046 {"brset.l", 1, 0x03, test_br_opr_reg_rel
, 0},
3048 {"brclr.b", 1, 0x02, test_br_opr_imm_rel
, 0},
3049 {"brclr.w", 1, 0x02, test_br_opr_imm_rel
, 0},
3050 {"brclr.l", 1, 0x02, test_br_opr_imm_rel
, 0},
3052 {"brset.b", 1, 0x03, test_br_opr_imm_rel
, 0},
3053 {"brset.w", 1, 0x03, test_br_opr_imm_rel
, 0},
3054 {"brset.l", 1, 0x03, test_br_opr_imm_rel
, 0},
3056 {"psh", 1, 0x04, psh_pull
, 0},
3057 {"pul", 1, 0x04, psh_pull
, 0},
3059 {"rts", 1, 0x05, no_operands
, 0},
3060 {"lea", 1, 0x06, reg67sxy_opr
, 0},
3062 {"dbne", 1, 0x0b, tb_reg_rel
, 0},
3063 {"dbeq", 1, 0x0b, tb_reg_rel
, 0},
3064 {"dbpl", 1, 0x0b, tb_reg_rel
, 0},
3065 {"dbmi", 1, 0x0b, tb_reg_rel
, 0},
3066 {"dbgt", 1, 0x0b, tb_reg_rel
, 0},
3067 {"dble", 1, 0x0b, tb_reg_rel
, 0},
3069 {"dbne.b", 1, 0x0b, tb_opr_rel
, 0},
3070 {"dbeq.b", 1, 0x0b, tb_opr_rel
, 0},
3071 {"dbpl.b", 1, 0x0b, tb_opr_rel
, 0},
3072 {"dbmi.b", 1, 0x0b, tb_opr_rel
, 0},
3073 {"dbgt.b", 1, 0x0b, tb_opr_rel
, 0},
3074 {"dble.b", 1, 0x0b, tb_opr_rel
, 0},
3076 {"dbne.w", 1, 0x0b, tb_opr_rel
, 0},
3077 {"dbeq.w", 1, 0x0b, tb_opr_rel
, 0},
3078 {"dbpl.w", 1, 0x0b, tb_opr_rel
, 0},
3079 {"dbmi.w", 1, 0x0b, tb_opr_rel
, 0},
3080 {"dbgt.w", 1, 0x0b, tb_opr_rel
, 0},
3081 {"dble.w", 1, 0x0b, tb_opr_rel
, 0},
3083 {"dbne.p", 1, 0x0b, tb_opr_rel
, 0},
3084 {"dbeq.p", 1, 0x0b, tb_opr_rel
, 0},
3085 {"dbpl.p", 1, 0x0b, tb_opr_rel
, 0},
3086 {"dbmi.p", 1, 0x0b, tb_opr_rel
, 0},
3087 {"dbgt.p", 1, 0x0b, tb_opr_rel
, 0},
3088 {"dble.p", 1, 0x0b, tb_opr_rel
, 0},
3090 {"dbne.l", 1, 0x0b, tb_opr_rel
, 0},
3091 {"dbeq.l", 1, 0x0b, tb_opr_rel
, 0},
3092 {"dbpl.l", 1, 0x0b, tb_opr_rel
, 0},
3093 {"dbmi.l", 1, 0x0b, tb_opr_rel
, 0},
3094 {"dbgt.l", 1, 0x0b, tb_opr_rel
, 0},
3095 {"dble.l", 1, 0x0b, tb_opr_rel
, 0},
3097 {"tbne", 1, 0x0b, tb_reg_rel
, 0},
3098 {"tbeq", 1, 0x0b, tb_reg_rel
, 0},
3099 {"tbpl", 1, 0x0b, tb_reg_rel
, 0},
3100 {"tbmi", 1, 0x0b, tb_reg_rel
, 0},
3101 {"tbgt", 1, 0x0b, tb_reg_rel
, 0},
3102 {"tble", 1, 0x0b, tb_reg_rel
, 0},
3104 {"tbne.b", 1, 0x0b, tb_opr_rel
, 0},
3105 {"tbeq.b", 1, 0x0b, tb_opr_rel
, 0},
3106 {"tbpl.b", 1, 0x0b, tb_opr_rel
, 0},
3107 {"tbmi.b", 1, 0x0b, tb_opr_rel
, 0},
3108 {"tbgt.b", 1, 0x0b, tb_opr_rel
, 0},
3109 {"tble.b", 1, 0x0b, tb_opr_rel
, 0},
3111 {"tbne.w", 1, 0x0b, tb_opr_rel
, 0},
3112 {"tbeq.w", 1, 0x0b, tb_opr_rel
, 0},
3113 {"tbpl.w", 1, 0x0b, tb_opr_rel
, 0},
3114 {"tbmi.w", 1, 0x0b, tb_opr_rel
, 0},
3115 {"tbgt.w", 1, 0x0b, tb_opr_rel
, 0},
3116 {"tble.w", 1, 0x0b, tb_opr_rel
, 0},
3118 {"tbne.p", 1, 0x0b, tb_opr_rel
, 0},
3119 {"tbeq.p", 1, 0x0b, tb_opr_rel
, 0},
3120 {"tbpl.p", 1, 0x0b, tb_opr_rel
, 0},
3121 {"tbmi.p", 1, 0x0b, tb_opr_rel
, 0},
3122 {"tbgt.p", 1, 0x0b, tb_opr_rel
, 0},
3123 {"tble.p", 1, 0x0b, tb_opr_rel
, 0},
3125 {"tbne.l", 1, 0x0b, tb_opr_rel
, 0},
3126 {"tbeq.l", 1, 0x0b, tb_opr_rel
, 0},
3127 {"tbpl.l", 1, 0x0b, tb_opr_rel
, 0},
3128 {"tbmi.l", 1, 0x0b, tb_opr_rel
, 0},
3129 {"tbgt.l", 1, 0x0b, tb_opr_rel
, 0},
3130 {"tble.l", 1, 0x0b, tb_opr_rel
, 0},
3132 {"mov.b", 1, 0x0c, imm_opr
, 0},
3133 {"mov.w", 1, 0x0d, imm_opr
, 0},
3134 {"mov.p", 1, 0x0e, imm_opr
, 0},
3135 {"mov.l", 1, 0x0f, imm_opr
, 0},
3137 {"rol", 1, 0x10, rol
, 0},
3138 {"rol.b", 1, 0x10, rol
, 0},
3139 {"rol.w", 1, 0x10, rol
, 0},
3140 {"rol.p", 1, 0x10, rol
, 0},
3141 {"rol.l", 1, 0x10, rol
, 0},
3143 {"ror", 1, 0x10, ror
, 0},
3144 {"ror.b", 1, 0x10, ror
, 0},
3145 {"ror.w", 1, 0x10, ror
, 0},
3146 {"ror.p", 1, 0x10, ror
, 0},
3147 {"ror.l", 1, 0x10, ror
, 0},
3149 {"lsl", 1, 0x10, shift_reg
, 0},
3150 {"lsr", 1, 0x10, shift_reg
, 0},
3151 {"asl", 1, 0x10, shift_reg
, 0},
3152 {"asr", 1, 0x10, shift_reg
, 0},
3154 {"lsl.b", 1, 0x10, shift_two_operand
, 0},
3155 {"lsl.w", 1, 0x10, shift_two_operand
, 0},
3156 {"lsl.p", 1, 0x10, shift_two_operand
, 0},
3157 {"lsl.l", 1, 0x10, shift_two_operand
, 0},
3158 {"asl.b", 1, 0x10, shift_two_operand
, 0},
3159 {"asl.w", 1, 0x10, shift_two_operand
, 0},
3160 {"asl.p", 1, 0x10, shift_two_operand
, 0},
3161 {"asl.l", 1, 0x10, shift_two_operand
, 0},
3163 {"lsr.b", 1, 0x10, shift_two_operand
, 0},
3164 {"lsr.w", 1, 0x10, shift_two_operand
, 0},
3165 {"lsr.p", 1, 0x10, shift_two_operand
, 0},
3166 {"lsr.l", 1, 0x10, shift_two_operand
, 0},
3167 {"asr.b", 1, 0x10, shift_two_operand
, 0},
3168 {"asr.w", 1, 0x10, shift_two_operand
, 0},
3169 {"asr.p", 1, 0x10, shift_two_operand
, 0},
3170 {"asr.l", 1, 0x10, shift_two_operand
, 0},
3172 {"lsl.b", 1, 0x10, shift_opr_imm
, 0},
3173 {"lsl.w", 1, 0x10, shift_opr_imm
, 0},
3174 {"lsl.p", 1, 0x10, shift_opr_imm
, 0},
3175 {"lsl.l", 1, 0x10, shift_opr_imm
, 0},
3176 {"asl.b", 1, 0x10, shift_opr_imm
, 0},
3177 {"asl.w", 1, 0x10, shift_opr_imm
, 0},
3178 {"asl.p", 1, 0x10, shift_opr_imm
, 0},
3179 {"asl.l", 1, 0x10, shift_opr_imm
, 0},
3181 {"lsr.b", 1, 0x10, shift_opr_imm
, 0},
3182 {"lsr.w", 1, 0x10, shift_opr_imm
, 0},
3183 {"lsr.p", 1, 0x10, shift_opr_imm
, 0},
3184 {"lsr.l", 1, 0x10, shift_opr_imm
, 0},
3185 {"asr.b", 1, 0x10, shift_opr_imm
, 0},
3186 {"asr.w", 1, 0x10, shift_opr_imm
, 0},
3187 {"asr.p", 1, 0x10, shift_opr_imm
, 0},
3188 {"asr.l", 1, 0x10, shift_opr_imm
, 0},
3190 {"mov.b", 1, 0x1c, opr_opr
, 0},
3191 {"mov.w", 1, 0x1d, opr_opr
, 0},
3192 {"mov.p", 1, 0x1e, opr_opr
, 0},
3193 {"mov.l", 1, 0x1f, opr_opr
, 0},
3195 {"bra", 1, 0x20, rel
, 0},
3196 {"bsr", 1, 0x21, rel
, 0},
3197 {"bhi", 1, 0x22, rel
, 0},
3198 {"bls", 1, 0x23, rel
, 0},
3199 {"bcc", 1, 0x24, rel
, 0},
3200 {"bhs", 1, 0x24, rel
, 0}, /* Alias for bcc */
3201 {"bcs", 1, 0x25, rel
, 0},
3202 {"blo", 1, 0x25, rel
, 0}, /* Alias for bcs */
3203 {"bne", 1, 0x26, rel
, 0},
3204 {"beq", 1, 0x27, rel
, 0},
3205 {"bvc", 1, 0x28, rel
, 0},
3206 {"bvs", 1, 0x29, rel
, 0},
3207 {"bpl", 1, 0x2a, rel
, 0},
3208 {"bmi", 1, 0x2b, rel
, 0},
3209 {"bge", 1, 0x2c, rel
, 0},
3210 {"blt", 1, 0x2d, rel
, 0},
3211 {"bgt", 1, 0x2e, rel
, 0},
3212 {"ble", 1, 0x2f, rel
, 0},
3214 {"inc", 1, 0x30, reg_inh
, 0},
3215 {"clr", 1, 0x38, reg_inh
, 0},
3216 {"dec", 1, 0x40, reg_inh
, 0},
3218 {"muls", 1, 0x48, mul_reg_reg_reg
, 0},
3219 {"mulu", 1, 0x48, mul_reg_reg_reg
, 0},
3221 {"muls.b", 1, 0x48, mul_reg_reg_opr
, 0},
3222 {"muls.w", 1, 0x48, mul_reg_reg_opr
, 0},
3223 {"muls.l", 1, 0x48, mul_reg_reg_opr
, 0},
3225 {"mulu.b", 1, 0x48, mul_reg_reg_opr
, 0},
3226 {"mulu.w", 1, 0x48, mul_reg_reg_opr
, 0},
3227 {"mulu.l", 1, 0x48, mul_reg_reg_opr
, 0},
3229 {"muls.b", 1, 0x48, mul_reg_reg_imm
, 0},
3230 {"muls.w", 1, 0x48, mul_reg_reg_imm
, 0},
3231 {"muls.l", 1, 0x48, mul_reg_reg_imm
, 0},
3233 {"mulu.b", 1, 0x48, mul_reg_reg_imm
, 0},
3234 {"mulu.w", 1, 0x48, mul_reg_reg_imm
, 0},
3235 {"mulu.l", 1, 0x48, mul_reg_reg_imm
, 0},
3237 {"muls.bb", 1, 0x48, mul_reg_opr_opr
, 0},
3238 {"muls.bw", 1, 0x48, mul_reg_opr_opr
, 0},
3239 {"muls.bp", 1, 0x48, mul_reg_opr_opr
, 0},
3240 {"muls.bl", 1, 0x48, mul_reg_opr_opr
, 0},
3242 {"muls.wb", 1, 0x48, mul_reg_opr_opr
, 0},
3243 {"muls.ww", 1, 0x48, mul_reg_opr_opr
, 0},
3244 {"muls.wp", 1, 0x48, mul_reg_opr_opr
, 0},
3245 {"muls.wl", 1, 0x48, mul_reg_opr_opr
, 0},
3247 {"muls.pb", 1, 0x48, mul_reg_opr_opr
, 0},
3248 {"muls.pw", 1, 0x48, mul_reg_opr_opr
, 0},
3249 {"muls.pp", 1, 0x48, mul_reg_opr_opr
, 0},
3250 {"muls.pl", 1, 0x48, mul_reg_opr_opr
, 0},
3252 {"muls.lb", 1, 0x48, mul_reg_opr_opr
, 0},
3253 {"muls.lw", 1, 0x48, mul_reg_opr_opr
, 0},
3254 {"muls.lp", 1, 0x48, mul_reg_opr_opr
, 0},
3255 {"muls.ll", 1, 0x48, mul_reg_opr_opr
, 0},
3257 {"mulu.bb", 1, 0x48, mul_reg_opr_opr
, 0},
3258 {"mulu.bw", 1, 0x48, mul_reg_opr_opr
, 0},
3259 {"mulu.bp", 1, 0x48, mul_reg_opr_opr
, 0},
3260 {"mulu.bl", 1, 0x48, mul_reg_opr_opr
, 0},
3262 {"mulu.wb", 1, 0x48, mul_reg_opr_opr
, 0},
3263 {"mulu.ww", 1, 0x48, mul_reg_opr_opr
, 0},
3264 {"mulu.wp", 1, 0x48, mul_reg_opr_opr
, 0},
3265 {"mulu.wl", 1, 0x48, mul_reg_opr_opr
, 0},
3267 {"mulu.pb", 1, 0x48, mul_reg_opr_opr
, 0},
3268 {"mulu.pw", 1, 0x48, mul_reg_opr_opr
, 0},
3269 {"mulu.pp", 1, 0x48, mul_reg_opr_opr
, 0},
3270 {"mulu.pl", 1, 0x48, mul_reg_opr_opr
, 0},
3272 {"mulu.lb", 1, 0x48, mul_reg_opr_opr
, 0},
3273 {"mulu.lw", 1, 0x48, mul_reg_opr_opr
, 0},
3274 {"mulu.lp", 1, 0x48, mul_reg_opr_opr
, 0},
3275 {"mulu.ll", 1, 0x48, mul_reg_opr_opr
, 0},
3277 {"add", 1, 0x50, regd_imm
, 0},
3278 {"and", 1, 0x58, regd_imm
, 0},
3280 {"add", 1, 0x60, regd_opr
, 0},
3281 {"and", 1, 0x68, regd_opr
, 0},
3283 {"sub", 1, 0x70, regd_imm
, 0},
3284 {"or", 1, 0x78, regd_imm
, 0},
3286 {"sub", 1, 0x80, regd_opr
, 0},
3287 {"or", 1, 0x88, regd_opr
, 0},
3289 {"ld", 1, 0x90, regdxy_imm
, 0},
3291 {"clr", 1, 0x9a, clr_xy
, 0},
3292 {"tfr", 1, 0x9e, tfr
, 0},
3293 {"zex", 1, 0x9e, tfr
, 0},
3295 {"ld", 1, 0xa0, regdxy_opr_src
, 0xb0},
3297 {"jmp", 1, 0xaa, opr
, 0xba},
3298 {"jsr", 1, 0xab, opr
, 0xbb},
3300 {"exg", 1, 0xae, tfr
, 0},
3301 {"sex", 1, 0xae, tfr
, 0},
3303 {"st", 1, 0xc0, regdxy_opr_dest
, 0xd0},
3305 {"andcc", 1, 0xce, imm8
, 0},
3306 {"orcc", 1, 0xde, imm8
, 0},
3308 {"inc.b", 1, 0x9c, opr
, 0},
3309 {"inc.w", 1, 0x9d, opr
, 0},
3310 {"inc.l", 1, 0x9f, opr
, 0},
3312 {"dec.b", 1, 0xac, opr
, 0},
3313 {"dec.w", 1, 0xad, opr
, 0},
3314 {"dec.l", 1, 0xaf, opr
, 0},
3316 {"clr.b", 1, 0xbc, opr
, 0},
3317 {"clr.w", 1, 0xbd, opr
, 0},
3318 {"clr.p", 1, 0xbe, opr
, 0},
3319 {"clr.l", 1, 0xbf, opr
, 0},
3321 {"com.b", 1, 0xcc, opr
, 0},
3322 {"com.w", 1, 0xcd, opr
, 0},
3323 {"com.l", 1, 0xcf, opr
, 0},
3325 {"neg.b", 1, 0xdc, opr
, 0},
3326 {"neg.w", 1, 0xdd, opr
, 0},
3327 {"neg.l", 1, 0xdf, opr
, 0},
3329 {"bclr", 1, 0xec, bm_regd_imm
, 0},
3330 {"bset", 1, 0xed, bm_regd_imm
, 0},
3331 {"btgl", 1, 0xee, bm_regd_imm
, 0},
3333 {"bclr", 1, 0xec, bm_regd_reg
, 0},
3334 {"bset", 1, 0xed, bm_regd_reg
, 0},
3335 {"btgl", 1, 0xee, bm_regd_reg
, 0},
3337 {"bclr.b", 1, 0xec, bm_opr_imm
, 0},
3338 {"bclr.w", 1, 0xec, bm_opr_imm
, 0},
3339 {"bclr.l", 1, 0xec, bm_opr_imm
, 0},
3341 {"bset.b", 1, 0xed, bm_opr_imm
, 0},
3342 {"bset.w", 1, 0xed, bm_opr_imm
, 0},
3343 {"bset.l", 1, 0xed, bm_opr_imm
, 0},
3345 {"btgl.b", 1, 0xee, bm_opr_imm
, 0},
3346 {"btgl.w", 1, 0xee, bm_opr_imm
, 0},
3347 {"btgl.l", 1, 0xee, bm_opr_imm
, 0},
3349 {"bclr.b", 1, 0xec, bm_opr_reg
, 0},
3350 {"bclr.w", 1, 0xec, bm_opr_reg
, 0},
3351 {"bclr.l", 1, 0xec, bm_opr_reg
, 0},
3353 {"bset.b", 1, 0xed, bm_opr_reg
, 0},
3354 {"bset.w", 1, 0xed, bm_opr_reg
, 0},
3355 {"bset.l", 1, 0xed, bm_opr_reg
, 0},
3357 {"btgl.b", 1, 0xee, bm_opr_reg
, 0},
3358 {"btgl.w", 1, 0xee, bm_opr_reg
, 0},
3359 {"btgl.l", 1, 0xee, bm_opr_reg
, 0},
3361 {"cmp", 1, 0xe0, regdxy_imm
, 0},
3362 {"cmp", 1, 0xf0, regdxy_opr_src
, 0},
3364 {"cmp", 1, 0xfc, regx_regy
, 0},
3365 {"sub", 1, 0xfd, regd6_regx_regy
, 0},
3366 {"sub", 1, 0xfe, regd6_regy_regx
, 0},
3368 {"swi", 1, 0xff, no_operands
, 0},
3372 /* The -10 below is a kludge. The opcode is in fact 0x00 */
3373 {"ld", 2, -10, regs_opr_src
, 0},
3375 /* The -9 below is a kludge. The opcode is in fact 0x01 */
3376 {"st", 2, -9, regs_opr_dest
, 0},
3378 /* The -8 below is a kludge. The opcode is in fact 0x02 */
3379 {"cmp", 2, -8, regs_opr_src
, 0},
3381 /* The -7 below is a kludge. The opcode is in fact 0x03 */
3382 {"ld", 2, -7, regs_imm
, 0},
3384 /* The -6 below is a kludge. The opcode is in fact 0x04 */
3385 {"cmp", 2, -6, regs_imm
, 0},
3387 {"bfext", 2, 0x08, bfe_reg_reg_reg
, 0},
3388 {"bfext", 2, 0x08, bfe_reg_reg_imm
, 0},
3389 {"bfext.b", 2, 0x08, bfe_reg_opr_reg
, 0},
3390 {"bfext.w", 2, 0x08, bfe_reg_opr_reg
, 0},
3391 {"bfext.p", 2, 0x08, bfe_reg_opr_reg
, 0},
3392 {"bfext.l", 2, 0x08, bfe_reg_opr_reg
, 0},
3393 {"bfext.b", 2, 0x08, bfe_opr_reg_reg
, 0},
3394 {"bfext.w", 2, 0x08, bfe_opr_reg_reg
, 0},
3395 {"bfext.p", 2, 0x08, bfe_opr_reg_reg
, 0},
3396 {"bfext.l", 2, 0x08, bfe_opr_reg_reg
, 0},
3397 {"bfext.b", 2, 0x08, bfe_reg_opr_imm
, 0},
3398 {"bfext.w", 2, 0x08, bfe_reg_opr_imm
, 0},
3399 {"bfext.p", 2, 0x08, bfe_reg_opr_imm
, 0},
3400 {"bfext.l", 2, 0x08, bfe_reg_opr_imm
, 0},
3401 {"bfext.b", 2, 0x08, bfe_opr_reg_imm
, 0},
3402 {"bfext.w", 2, 0x08, bfe_opr_reg_imm
, 0},
3403 {"bfext.p", 2, 0x08, bfe_opr_reg_imm
, 0},
3404 {"bfext.l", 2, 0x08, bfe_opr_reg_imm
, 0},
3407 {"bfins", 2, 0x08, bfi_reg_reg_reg
, 0},
3408 {"bfins", 2, 0x08, bfi_reg_reg_imm
, 0},
3409 {"bfins.b", 2, 0x08, bfi_reg_opr_reg
, 0},
3410 {"bfins.w", 2, 0x08, bfi_reg_opr_reg
, 0},
3411 {"bfins.p", 2, 0x08, bfi_reg_opr_reg
, 0},
3412 {"bfins.l", 2, 0x08, bfi_reg_opr_reg
, 0},
3413 {"bfins.b", 2, 0x08, bfi_opr_reg_reg
, 0},
3414 {"bfins.w", 2, 0x08, bfi_opr_reg_reg
, 0},
3415 {"bfins.p", 2, 0x08, bfi_opr_reg_reg
, 0},
3416 {"bfins.l", 2, 0x08, bfi_opr_reg_reg
, 0},
3417 {"bfins.b", 2, 0x08, bfi_reg_opr_imm
, 0},
3418 {"bfins.w", 2, 0x08, bfi_reg_opr_imm
, 0},
3419 {"bfins.p", 2, 0x08, bfi_reg_opr_imm
, 0},
3420 {"bfins.l", 2, 0x08, bfi_reg_opr_imm
, 0},
3421 {"bfins.b", 2, 0x08, bfi_opr_reg_imm
, 0},
3422 {"bfins.w", 2, 0x08, bfi_opr_reg_imm
, 0},
3423 {"bfins.p", 2, 0x08, bfi_opr_reg_imm
, 0},
3424 {"bfins.l", 2, 0x08, bfi_opr_reg_imm
, 0},
3427 {"minu", 2, 0x10, regd_opr
, 0},
3428 {"maxu", 2, 0x18, regd_opr
, 0},
3429 {"mins", 2, 0x20, regd_opr
, 0},
3430 {"maxs", 2, 0x28, regd_opr
, 0},
3432 {"clb", 2, 0x91, tfr
, 0},
3434 {"trap", 2, 0x00, trap_imm
, 0},
3435 {"abs", 2, 0x40, reg_inh
, 0},
3436 {"sat", 2, 0xa0, reg_inh
, 0},
3438 {"rti", 2, 0x90, no_operands
, 0},
3439 {"stop", 2, 0x05, no_operands
, 0},
3440 {"wai", 2, 0x06, no_operands
, 0},
3441 {"sys", 2, 0x07, no_operands
, 0},
3443 {"bit", 2, 0x58, regd_imm
, 0},
3444 {"bit", 2, 0x68, regd_opr
, 0},
3446 {"adc", 2, 0x50, regd_imm
, 0},
3447 {"adc", 2, 0x60, regd_opr
, 0},
3449 {"sbc", 2, 0x70, regd_imm
, 0},
3450 {"eor", 2, 0x78, regd_imm
, 0},
3452 {"sbc", 2, 0x80, regd_opr
, 0},
3453 {"eor", 2, 0x88, regd_opr
, 0},
3455 {"divs", 2, 0x30, mul_reg_reg_reg
, 0},
3456 {"divu", 2, 0x30, mul_reg_reg_reg
, 0},
3458 {"divs.b", 2, 0x30, mul_reg_reg_opr
, 0},
3459 {"divs.w", 2, 0x30, mul_reg_reg_opr
, 0},
3460 {"divs.l", 2, 0x30, mul_reg_reg_opr
, 0},
3462 {"divu.b", 2, 0x30, mul_reg_reg_opr
, 0},
3463 {"divu.w", 2, 0x30, mul_reg_reg_opr
, 0},
3464 {"divu.l", 2, 0x30, mul_reg_reg_opr
, 0},
3466 {"divs.b", 2, 0x30, mul_reg_reg_imm
, 0},
3467 {"divs.w", 2, 0x30, mul_reg_reg_imm
, 0},
3468 {"divs.l", 2, 0x30, mul_reg_reg_imm
, 0},
3470 {"divu.b", 2, 0x30, mul_reg_reg_imm
, 0},
3471 {"divu.w", 2, 0x30, mul_reg_reg_imm
, 0},
3472 {"divu.l", 2, 0x30, mul_reg_reg_imm
, 0},
3474 {"divs.bb", 2, 0x30, mul_reg_opr_opr
, 0},
3475 {"divs.bw", 2, 0x30, mul_reg_opr_opr
, 0},
3476 {"divs.bp", 2, 0x30, mul_reg_opr_opr
, 0},
3477 {"divs.bl", 2, 0x30, mul_reg_opr_opr
, 0},
3479 {"divs.wb", 2, 0x30, mul_reg_opr_opr
, 0},
3480 {"divs.ww", 2, 0x30, mul_reg_opr_opr
, 0},
3481 {"divs.wp", 2, 0x30, mul_reg_opr_opr
, 0},
3482 {"divs.wl", 2, 0x30, mul_reg_opr_opr
, 0},
3484 {"divs.pb", 2, 0x30, mul_reg_opr_opr
, 0},
3485 {"divs.pw", 2, 0x30, mul_reg_opr_opr
, 0},
3486 {"divs.pp", 2, 0x30, mul_reg_opr_opr
, 0},
3487 {"divs.pl", 2, 0x30, mul_reg_opr_opr
, 0},
3489 {"divs.lb", 2, 0x30, mul_reg_opr_opr
, 0},
3490 {"divs.lw", 2, 0x30, mul_reg_opr_opr
, 0},
3491 {"divs.lp", 2, 0x30, mul_reg_opr_opr
, 0},
3492 {"divs.ll", 2, 0x30, mul_reg_opr_opr
, 0},
3494 {"divu.bb", 2, 0x30, mul_reg_opr_opr
, 0},
3495 {"divu.bw", 2, 0x30, mul_reg_opr_opr
, 0},
3496 {"divu.bp", 2, 0x30, mul_reg_opr_opr
, 0},
3497 {"divu.bl", 2, 0x30, mul_reg_opr_opr
, 0},
3499 {"divu.wb", 2, 0x30, mul_reg_opr_opr
, 0},
3500 {"divu.ww", 2, 0x30, mul_reg_opr_opr
, 0},
3501 {"divu.wp", 2, 0x30, mul_reg_opr_opr
, 0},
3502 {"divu.wl", 2, 0x30, mul_reg_opr_opr
, 0},
3504 {"divu.pb", 2, 0x30, mul_reg_opr_opr
, 0},
3505 {"divu.pw", 2, 0x30, mul_reg_opr_opr
, 0},
3506 {"divu.pp", 2, 0x30, mul_reg_opr_opr
, 0},
3507 {"divu.pl", 2, 0x30, mul_reg_opr_opr
, 0},
3509 {"divu.lb", 2, 0x30, mul_reg_opr_opr
, 0},
3510 {"divu.lw", 2, 0x30, mul_reg_opr_opr
, 0},
3511 {"divu.lp", 2, 0x30, mul_reg_opr_opr
, 0},
3512 {"divu.ll", 2, 0x30, mul_reg_opr_opr
, 0},
3516 {"qmuls", 2, 0xb0, mul_reg_reg_reg
, 0},
3517 {"qmulu", 2, 0xb0, mul_reg_reg_reg
, 0},
3519 {"qmuls.b", 2, 0xb0, mul_reg_reg_opr
, 0},
3520 {"qmuls.w", 2, 0xb0, mul_reg_reg_opr
, 0},
3521 {"qmuls.l", 2, 0xb0, mul_reg_reg_opr
, 0},
3523 {"qmulu.b", 2, 0xb0, mul_reg_reg_opr
, 0},
3524 {"qmulu.w", 2, 0xb0, mul_reg_reg_opr
, 0},
3525 {"qmulu.l", 2, 0xb0, mul_reg_reg_opr
, 0},
3527 {"qmuls.b", 2, 0xb0, mul_reg_reg_imm
, 0},
3528 {"qmuls.w", 2, 0xb0, mul_reg_reg_imm
, 0},
3529 {"qmuls.l", 2, 0xb0, mul_reg_reg_imm
, 0},
3531 {"qmulu.b", 2, 0xb0, mul_reg_reg_imm
, 0},
3532 {"qmulu.w", 2, 0xb0, mul_reg_reg_imm
, 0},
3533 {"qmulu.l", 2, 0xb0, mul_reg_reg_imm
, 0},
3535 {"qmuls.bb", 2, 0xb0, mul_reg_opr_opr
, 0},
3536 {"qmuls.bw", 2, 0xb0, mul_reg_opr_opr
, 0},
3537 {"qmuls.bp", 2, 0xb0, mul_reg_opr_opr
, 0},
3538 {"qmuls.bl", 2, 0xb0, mul_reg_opr_opr
, 0},
3540 {"qmuls.wb", 2, 0xb0, mul_reg_opr_opr
, 0},
3541 {"qmuls.ww", 2, 0xb0, mul_reg_opr_opr
, 0},
3542 {"qmuls.wp", 2, 0xb0, mul_reg_opr_opr
, 0},
3543 {"qmuls.wl", 2, 0xb0, mul_reg_opr_opr
, 0},
3545 {"qmuls.pb", 2, 0xb0, mul_reg_opr_opr
, 0},
3546 {"qmuls.pw", 2, 0xb0, mul_reg_opr_opr
, 0},
3547 {"qmuls.pp", 2, 0xb0, mul_reg_opr_opr
, 0},
3548 {"qmuls.pl", 2, 0xb0, mul_reg_opr_opr
, 0},
3550 {"qmuls.lb", 2, 0xb0, mul_reg_opr_opr
, 0},
3551 {"qmuls.lw", 2, 0xb0, mul_reg_opr_opr
, 0},
3552 {"qmuls.lp", 2, 0xb0, mul_reg_opr_opr
, 0},
3553 {"qmuls.ll", 2, 0xb0, mul_reg_opr_opr
, 0},
3555 {"qmulu.bb", 2, 0xb0, mul_reg_opr_opr
, 0},
3556 {"qmulu.bw", 2, 0xb0, mul_reg_opr_opr
, 0},
3557 {"qmulu.bp", 2, 0xb0, mul_reg_opr_opr
, 0},
3558 {"qmulu.bl", 2, 0xb0, mul_reg_opr_opr
, 0},
3560 {"qmulu.wb", 2, 0xb0, mul_reg_opr_opr
, 0},
3561 {"qmulu.ww", 2, 0xb0, mul_reg_opr_opr
, 0},
3562 {"qmulu.wp", 2, 0xb0, mul_reg_opr_opr
, 0},
3563 {"qmulu.wl", 2, 0xb0, mul_reg_opr_opr
, 0},
3565 {"qmulu.pb", 2, 0xb0, mul_reg_opr_opr
, 0},
3566 {"qmulu.pw", 2, 0xb0, mul_reg_opr_opr
, 0},
3567 {"qmulu.pp", 2, 0xb0, mul_reg_opr_opr
, 0},
3568 {"qmulu.pl", 2, 0xb0, mul_reg_opr_opr
, 0},
3570 {"qmulu.lb", 2, 0xb0, mul_reg_opr_opr
, 0},
3571 {"qmulu.lw", 2, 0xb0, mul_reg_opr_opr
, 0},
3572 {"qmulu.lp", 2, 0xb0, mul_reg_opr_opr
, 0},
3573 {"qmulu.ll", 2, 0xb0, mul_reg_opr_opr
, 0},
3578 {"macs", 2, 0x48, mul_reg_reg_reg
, 0},
3579 {"macu", 2, 0x48, mul_reg_reg_reg
, 0},
3581 {"macs.b", 2, 0x48, mul_reg_reg_opr
, 0},
3582 {"macs.w", 2, 0x48, mul_reg_reg_opr
, 0},
3583 {"macs.l", 2, 0x48, mul_reg_reg_opr
, 0},
3585 {"macu.b", 2, 0x48, mul_reg_reg_opr
, 0},
3586 {"macu.w", 2, 0x48, mul_reg_reg_opr
, 0},
3587 {"macu.l", 2, 0x48, mul_reg_reg_opr
, 0},
3589 {"macs.b", 2, 0x48, mul_reg_reg_imm
, 0},
3590 {"macs.w", 2, 0x48, mul_reg_reg_imm
, 0},
3591 {"macs.l", 2, 0x48, mul_reg_reg_imm
, 0},
3593 {"macu.b", 2, 0x48, mul_reg_reg_imm
, 0},
3594 {"macu.w", 2, 0x48, mul_reg_reg_imm
, 0},
3595 {"macu.l", 2, 0x48, mul_reg_reg_imm
, 0},
3597 {"macs.bb", 2, 0x48, mul_reg_opr_opr
, 0},
3598 {"macs.bw", 2, 0x48, mul_reg_opr_opr
, 0},
3599 {"macs.bp", 2, 0x48, mul_reg_opr_opr
, 0},
3600 {"macs.bl", 2, 0x48, mul_reg_opr_opr
, 0},
3602 {"macs.wb", 2, 0x48, mul_reg_opr_opr
, 0},
3603 {"macs.ww", 2, 0x48, mul_reg_opr_opr
, 0},
3604 {"macs.wp", 2, 0x48, mul_reg_opr_opr
, 0},
3605 {"macs.wl", 2, 0x48, mul_reg_opr_opr
, 0},
3607 {"macs.pb", 2, 0x48, mul_reg_opr_opr
, 0},
3608 {"macs.pw", 2, 0x48, mul_reg_opr_opr
, 0},
3609 {"macs.pp", 2, 0x48, mul_reg_opr_opr
, 0},
3610 {"macs.pl", 2, 0x48, mul_reg_opr_opr
, 0},
3612 {"macs.lb", 2, 0x48, mul_reg_opr_opr
, 0},
3613 {"macs.lw", 2, 0x48, mul_reg_opr_opr
, 0},
3614 {"macs.lp", 2, 0x48, mul_reg_opr_opr
, 0},
3615 {"macs.ll", 2, 0x48, mul_reg_opr_opr
, 0},
3617 {"macu.bb", 2, 0x48, mul_reg_opr_opr
, 0},
3618 {"macu.bw", 2, 0x48, mul_reg_opr_opr
, 0},
3619 {"macu.bp", 2, 0x48, mul_reg_opr_opr
, 0},
3620 {"macu.bl", 2, 0x48, mul_reg_opr_opr
, 0},
3622 {"macu.wb", 2, 0x48, mul_reg_opr_opr
, 0},
3623 {"macu.ww", 2, 0x48, mul_reg_opr_opr
, 0},
3624 {"macu.wp", 2, 0x48, mul_reg_opr_opr
, 0},
3625 {"macu.wl", 2, 0x48, mul_reg_opr_opr
, 0},
3627 {"macu.pb", 2, 0x48, mul_reg_opr_opr
, 0},
3628 {"macu.pw", 2, 0x48, mul_reg_opr_opr
, 0},
3629 {"macu.pp", 2, 0x48, mul_reg_opr_opr
, 0},
3630 {"macu.pl", 2, 0x48, mul_reg_opr_opr
, 0},
3632 {"macu.lb", 2, 0x48, mul_reg_opr_opr
, 0},
3633 {"macu.lw", 2, 0x48, mul_reg_opr_opr
, 0},
3634 {"macu.lp", 2, 0x48, mul_reg_opr_opr
, 0},
3635 {"macu.ll", 2, 0x48, mul_reg_opr_opr
, 0},
3640 {"mods", 2, 0x38, mul_reg_reg_reg
, 0},
3641 {"modu", 2, 0x38, mul_reg_reg_reg
, 0},
3643 {"mods.b", 2, 0x38, mul_reg_reg_opr
, 0},
3644 {"mods.w", 2, 0x38, mul_reg_reg_opr
, 0},
3645 {"mods.l", 2, 0x38, mul_reg_reg_opr
, 0},
3647 {"modu.b", 2, 0x38, mul_reg_reg_opr
, 0},
3648 {"modu.w", 2, 0x38, mul_reg_reg_opr
, 0},
3649 {"modu.l", 2, 0x38, mul_reg_reg_opr
, 0},
3651 {"mods.b", 2, 0x38, mul_reg_reg_imm
, 0},
3652 {"mods.w", 2, 0x38, mul_reg_reg_imm
, 0},
3653 {"mods.l", 2, 0x38, mul_reg_reg_imm
, 0},
3655 {"modu.b", 2, 0x38, mul_reg_reg_imm
, 0},
3656 {"modu.w", 2, 0x38, mul_reg_reg_imm
, 0},
3657 {"modu.l", 2, 0x38, mul_reg_reg_imm
, 0},
3659 {"mods.bb", 2, 0x38, mul_reg_opr_opr
, 0},
3660 {"mods.bw", 2, 0x38, mul_reg_opr_opr
, 0},
3661 {"mods.bp", 2, 0x38, mul_reg_opr_opr
, 0},
3662 {"mods.bl", 2, 0x38, mul_reg_opr_opr
, 0},
3664 {"mods.wb", 2, 0x38, mul_reg_opr_opr
, 0},
3665 {"mods.ww", 2, 0x38, mul_reg_opr_opr
, 0},
3666 {"mods.wp", 2, 0x38, mul_reg_opr_opr
, 0},
3667 {"mods.wl", 2, 0x38, mul_reg_opr_opr
, 0},
3669 {"mods.pb", 2, 0x38, mul_reg_opr_opr
, 0},
3670 {"mods.pw", 2, 0x38, mul_reg_opr_opr
, 0},
3671 {"mods.pp", 2, 0x38, mul_reg_opr_opr
, 0},
3672 {"mods.pl", 2, 0x38, mul_reg_opr_opr
, 0},
3674 {"mods.lb", 2, 0x38, mul_reg_opr_opr
, 0},
3675 {"mods.lw", 2, 0x38, mul_reg_opr_opr
, 0},
3676 {"mods.lp", 2, 0x38, mul_reg_opr_opr
, 0},
3677 {"mods.ll", 2, 0x38, mul_reg_opr_opr
, 0},
3679 {"modu.bb", 2, 0x38, mul_reg_opr_opr
, 0},
3680 {"modu.bw", 2, 0x38, mul_reg_opr_opr
, 0},
3681 {"modu.bp", 2, 0x38, mul_reg_opr_opr
, 0},
3682 {"modu.bl", 2, 0x38, mul_reg_opr_opr
, 0},
3684 {"modu.wb", 2, 0x38, mul_reg_opr_opr
, 0},
3685 {"modu.ww", 2, 0x38, mul_reg_opr_opr
, 0},
3686 {"modu.wp", 2, 0x38, mul_reg_opr_opr
, 0},
3687 {"modu.wl", 2, 0x38, mul_reg_opr_opr
, 0},
3689 {"modu.pb", 2, 0x38, mul_reg_opr_opr
, 0},
3690 {"modu.pw", 2, 0x38, mul_reg_opr_opr
, 0},
3691 {"modu.pp", 2, 0x38, mul_reg_opr_opr
, 0},
3692 {"modu.pl", 2, 0x38, mul_reg_opr_opr
, 0},
3694 {"modu.lb", 2, 0x38, mul_reg_opr_opr
, 0},
3695 {"modu.lw", 2, 0x38, mul_reg_opr_opr
, 0},
3696 {"modu.lp", 2, 0x38, mul_reg_opr_opr
, 0},
3697 {"modu.ll", 2, 0x38, mul_reg_opr_opr
, 0}
3701 /* Gas line assembler entry point. */
3703 /* This is the main entry point for the machine-dependent assembler. str
3704 points to a machine-dependent instruction. This function is supposed to
3705 emit the frags/bytes it assembles to. */
3707 md_assemble (char *str
)
3714 fail_line_pointer
= NULL
;
3716 /* Find the opcode end and get the opcode in 'name'. The opcode is forced
3717 lower case (the opcode table only has lower case op-codes). */
3718 for (op_start
= op_end
= str
;
3719 *op_end
&& !is_end_of_line
[(int)*op_end
] && *op_end
!= ' ';
3722 name
[nlen
] = TOLOWER (op_start
[nlen
]);
3724 gas_assert (nlen
< sizeof (name
) - 1);
3730 as_bad (_("No instruction or missing opcode."));
3734 input_line_pointer
= skip_whites (op_end
);
3737 for (i
= 0; i
< sizeof (opcodes
) / sizeof (opcodes
[0]); ++i
)
3739 const struct instruction
*opc
= opcodes
+ i
;
3740 if (0 == strcmp (name
, opc
->name
))
3742 if (opc
->parse_operands (opc
))
3748 as_bad (_("Invalid instruction: \"%s\""), str
);
3749 as_bad (_("First invalid token: \"%s\""), fail_line_pointer
);
3750 while (*input_line_pointer
++)
3758 /* Relocation, relaxation and frag conversions. */
3760 /* PC-relative offsets are relative to the start of the
3761 next instruction. That is, the address of the offset, plus its
3762 size, since the offset is always the last part of the insn. */
3764 md_pcrel_from (fixS
*fixP
)
3766 long ret
= fixP
->fx_size
+ fixP
->fx_frag
->fr_address
;
3767 if (fixP
->fx_addsy
&& S_IS_DEFINED (fixP
->fx_addsy
))
3768 ret
+= fixP
->fx_where
;
3774 /* We need a port-specific relaxation function to cope with sym2 - sym1
3775 relative expressions with both symbols in the same segment (but not
3776 necessarily in the same frag as this insn), for example:
3777 ldab sym2-(sym1-2),pc
3779 The offset can be 5, 9 or 16 bits long. */
3782 s12z_relax_frag (segT seg ATTRIBUTE_UNUSED
, fragS
*fragP ATTRIBUTE_UNUSED
,
3783 long stretch ATTRIBUTE_UNUSED
)
3789 md_convert_frag (bfd
*abfd ATTRIBUTE_UNUSED
, asection
*sec ATTRIBUTE_UNUSED
,
3790 fragS
*fragP ATTRIBUTE_UNUSED
)
3794 /* On an ELF system, we can't relax a weak symbol. The weak symbol
3795 can be overridden at final link time by a non weak symbol. We can
3796 relax externally visible symbol because there is no shared library
3797 and such symbol can't be overridden (unless they are weak). */
3799 /* Force truly undefined symbols to their maximum size, and generally set up
3800 the frag list to be relaxed. */
3802 md_estimate_size_before_relax (fragS
*fragP ATTRIBUTE_UNUSED
, asection
*segment ATTRIBUTE_UNUSED
)
3808 /* If while processing a fixup, a reloc really needs to be created
3809 then it is done here. */
3811 tc_gen_reloc (asection
*section
, fixS
*fixp
)
3813 arelent
*reloc
= XNEW (arelent
);
3814 reloc
->sym_ptr_ptr
= XNEW (asymbol
*);
3815 *reloc
->sym_ptr_ptr
= symbol_get_bfdsym (fixp
->fx_addsy
);
3816 reloc
->address
= fixp
->fx_frag
->fr_address
+ fixp
->fx_where
;
3817 reloc
->howto
= bfd_reloc_type_lookup (stdoutput
, fixp
->fx_r_type
);
3818 if (reloc
->howto
== (reloc_howto_type
*) NULL
)
3820 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
3821 _("Relocation %d is not supported by object file format."),
3822 (int) fixp
->fx_r_type
);
3826 if (0 == (section
->flags
& SEC_CODE
))
3827 reloc
->addend
= fixp
->fx_offset
;
3829 reloc
->addend
= fixp
->fx_addnumber
;
3834 /* See whether we need to force a relocation into the output file. */
3836 tc_s12z_force_relocation (fixS
*fixP
)
3838 return generic_force_reloc (fixP
);
3841 /* Here we decide which fixups can be adjusted to make them relative
3842 to the beginning of the section instead of the symbol. Basically
3843 we need to make sure that the linker relaxation is done
3844 correctly, so in some cases we force the original symbol to be
3847 tc_s12z_fix_adjustable (fixS
*fixP ATTRIBUTE_UNUSED
)
3853 md_apply_fix (fixS
*fixP
, valueT
*valP
, segT seg ATTRIBUTE_UNUSED
)
3857 if (fixP
->fx_addsy
== (symbolS
*) NULL
)
3860 /* We don't actually support subtracting a symbol. */
3861 if (fixP
->fx_subsy
!= (symbolS
*) NULL
)
3862 as_bad_where (fixP
->fx_file
, fixP
->fx_line
, _("Expression too complex."));
3865 Patch the instruction with the resolved operand. Elf relocation
3866 info will also be generated to take care of linker/loader fixups.
3868 char *where
= fixP
->fx_frag
->fr_literal
+ fixP
->fx_where
;
3870 switch (fixP
->fx_r_type
)
3873 ((bfd_byte
*) where
)[0] = (bfd_byte
) value
;
3876 bfd_putb16 ((bfd_vma
) value
, (unsigned char *) where
);
3879 bfd_putb24 ((bfd_vma
) value
, (unsigned char *) where
);
3881 case BFD_RELOC_S12Z_OPR
:
3883 switch (fixP
->fx_size
)
3886 bfd_putb24 ((bfd_vma
) value
, (unsigned char *) where
);
3889 bfd_putb16 ((bfd_vma
) value
, (unsigned char *) where
);
3897 bfd_putb32 ((bfd_vma
) value
, (unsigned char *) where
);
3899 case BFD_RELOC_16_PCREL
:
3900 if (value
< -0x4000 || value
> 0x3FFF)
3901 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
3902 _("Value out of 16-bit range."));
3904 bfd_putb16 ((bfd_vma
) value
| 0x8000, (unsigned char *) where
);
3908 as_fatal (_("Line %d: unknown relocation type: 0x%x."),
3909 fixP
->fx_line
, fixP
->fx_r_type
);
3913 /* Set the ELF specific flags. */
3915 s12z_elf_final_processing (void)