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 int 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 */
234 char *ilp
= input_line_pointer
;
236 if (*input_line_pointer
!= '#')
239 input_line_pointer
++;
241 if (!lex_expression (&exp
))
244 if (exp
.X_op
!= O_constant
)
247 *v
= exp
.X_add_number
;
251 fail_line_pointer
= input_line_pointer
;
252 input_line_pointer
= ilp
;
256 /* Short mmediate operand */
258 lex_imm_e4 (long *val
)
260 char *ilp
= input_line_pointer
;
263 if ((*val
== -1) || (*val
> 0 && *val
<= 15))
268 fail_line_pointer
= input_line_pointer
;
269 input_line_pointer
= ilp
;
274 lex_match_string (const char *s
)
276 char *p
= input_line_pointer
;
277 while (p
!= 0 && *p
!= '\t' && *p
!= ' ' && *p
!= '\0')
282 size_t len
= p
- input_line_pointer
;
283 if (len
!= strlen (s
))
286 if (0 == strncasecmp (s
, input_line_pointer
, len
))
288 input_line_pointer
= p
;
295 /* Parse a register name.
296 WHICH is a ORwise combination of the registers which are accepted.
298 On success, REG will be filled with the index of the register which
299 was successfully scanned.
302 lex_reg_name (uint16_t which
, int *reg
)
304 char *p
= input_line_pointer
;
306 ((*p
>= 'a' && *p
<='z') || (*p
>= '0' && *p
<= '9') || (*p
>= 'A' && *p
<='Z')))
311 size_t len
= p
- input_line_pointer
;
317 for (i
= 0; i
< S12Z_N_REGISTERS
; ++i
)
319 gas_assert (registers
[i
].name
);
321 if (len
== strlen (registers
[i
].name
)
322 && 0 == strncasecmp (registers
[i
].name
, input_line_pointer
, len
))
324 if ((0x1U
<< i
) & which
)
326 input_line_pointer
= p
;
337 lex_force_match (char x
)
339 char *p
= input_line_pointer
;
342 as_bad (_("Expecting '%c'"), x
);
346 input_line_pointer
++;
351 lex_opr (uint8_t *buffer
, int *n_bytes
, expressionS
*exp
)
353 char *ilp
= input_line_pointer
;
354 uint8_t *xb
= buffer
;
357 exp
->X_op
= O_absent
;
360 if (lex_imm_e4 (&imm
))
370 else if (lex_reg_name (REG_BIT_Dn
, ®
))
377 else if (lex_match ('['))
379 if (lex_expression (exp
))
381 long c
= exp
->X_add_number
;
384 if (lex_reg_name (REG_BIT_XYSP
, ®
))
387 if (c
<= 255 && c
>= -256)
397 *xb
|= (reg
- REG_X
) << 4;
401 for (i
= 1; i
< *n_bytes
; ++i
)
403 buffer
[i
] = c
>> (8 * (*n_bytes
- i
- 1));
408 as_bad (_("Bad operand for constant offset"));
421 else if (lex_reg_name (REG_BIT_Dn
, ®
))
423 if (!lex_force_match (','))
427 if (lex_reg_name (REG_BIT_XY
, ®2
))
431 *xb
|= (reg2
- REG_X
) << 4;
436 as_bad (_("Invalid operand for register offset"));
444 if (!lex_force_match (']'))
448 else if (lex_match ('('))
451 if (lex_constant (&c
))
453 if (!lex_force_match (','))
456 if (lex_reg_name (REG_BIT_XYSP
, ®2
))
458 if (reg2
!= REG_P
&& c
>= 0 && c
<= 15)
462 *xb
|= (reg2
- REG_X
) << 4;
465 else if (c
>= -256 && c
<= 255)
469 *xb
|= (reg2
- REG_X
) << 4;
478 *xb
|= (reg2
- REG_X
) << 4;
484 else if (lex_reg_name (REG_BIT_Dn
, ®2
))
486 if (c
>= -1 * (long) (0x1u
<< 17)
488 c
< (long) (0x1u
<< 17) - 1)
493 *xb
|= ((c
>> 16) & 0x03) << 4;
509 as_bad (_("Bad operand for constant offset"));
513 else if (lex_reg_name (REG_BIT_Dn
, ®
))
518 if (lex_reg_name (REG_BIT_XYS
, ®2
))
522 *xb
|= (reg2
- REG_X
) << 4;
527 as_bad (_("Invalid operand for register offset"));
536 else if (lex_reg_name (REG_BIT_XYS
, ®
))
542 as_bad (_("Invalid register for postdecrement operation"));
548 else if (reg
== REG_Y
)
551 else if (lex_match ('+'))
556 else if (reg
== REG_Y
)
558 else if (reg
== REG_S
)
566 else if (lex_match ('+'))
568 if (lex_reg_name (REG_BIT_XY
, ®
))
573 else if (reg
== REG_Y
)
578 as_bad (_("Invalid register for preincrement operation"));
582 else if (lex_match ('-'))
584 if (lex_reg_name (REG_BIT_XYS
, ®
))
589 else if (reg
== REG_Y
)
591 else if (reg
== REG_S
)
596 as_bad (_("Invalid register for predecrement operation"));
605 if (! lex_match (')'))
609 else if (lex_expression (exp
))
616 if (exp
->X_op
== O_constant
)
618 valueT value
= exp
->X_add_number
;
620 if (value
< (0x1U
<< 14))
627 else if (value
< (0x1U
<< 19))
630 if (value
& (0x1U
<< 17))
632 if (value
& (0x1U
<< 16))
635 buffer
[1] = value
>> 8;
642 buffer
[1] = value
>> 16;
643 buffer
[2] = value
>> 8;
651 fail_line_pointer
= input_line_pointer
;
652 input_line_pointer
= ilp
;
657 lex_offset (long *val
)
660 char *p
= input_line_pointer
;
665 if (*p
!= '+' && *p
!= '-')
668 bool negative
= (*p
== '-');
672 *val
= strtol (p
, &end
, 0);
677 input_line_pointer
= end
;
688 typedef int (*parse_operand_func
) (const struct instruction
*);
694 /* The "page" to which the instruction belongs.
695 This is also only a hint. Some instructions might have modes in both
699 /* This is a hint - and only a hint - about the opcode of the instruction.
700 The parse_operand_func is free to ignore it.
704 parse_operand_func parse_operands
;
706 /* Some instructions can be encoded with a different opcode */
711 no_operands (const struct instruction
*insn
)
713 if (*input_line_pointer
!= '\0')
715 as_bad (_("Garbage at end of instruction"));
719 char *f
= s12z_new_insn (insn
->page
);
721 number_to_chars_bigendian (f
++, PAGE2_PREBYTE
, 1);
723 number_to_chars_bigendian (f
++, insn
->opc
, 1);
728 /* Emit the code for an OPR address mode operand */
730 emit_opr (char *f
, const uint8_t *buffer
, int n_bytes
, expressionS
*exp
)
733 number_to_chars_bigendian (f
++, buffer
[0], 1);
734 if (exp
->X_op
!= O_absent
&& exp
->X_op
!= O_constant
)
736 fixS
*fix
= fix_new_exp (frag_now
,
737 f
- frag_now
->fr_literal
,
742 /* Some third party tools seem to use the lower bits
743 of this addend for flags. They don't get added
744 to the final location. The purpose of these flags
745 is not known. We simply set it to zero. */
746 fix
->fx_addnumber
= 0x00;
748 for (i
= 1; i
< n_bytes
; ++i
)
749 number_to_chars_bigendian (f
++, buffer
[i
], 1);
754 /* Emit the code for a 24 bit direct address operand */
756 emit_ext24 (char *f
, long v
)
758 number_to_chars_bigendian (f
, v
, 3);
764 opr (const struct instruction
*insn
)
769 if (lex_opr (buffer
, &n_bytes
, &exp
))
771 /* Large constant direct values are more efficiently encoded as ext24 mode.
772 Otherwise a decision has to be deferred to a relax. */
773 if (exp
.X_op
== O_constant
775 && insn
->alt_opc
!= 0)
777 char *f
= s12z_new_insn (4);
779 /* I don't think there are any instances of page 2 opcodes in this case */
780 gas_assert (insn
->page
== 1);
782 number_to_chars_bigendian (f
++, insn
->alt_opc
, 1);
784 emit_ext24 (f
, exp
.X_add_number
);
788 char *f
= s12z_new_insn (n_bytes
+ 1);
789 number_to_chars_bigendian (f
++, insn
->opc
, 1);
791 emit_opr (f
, buffer
, n_bytes
, &exp
);
799 /* Parse a 15 bit offset, as an expression.
800 LONG_DISPLACEMENT will be set to true if the offset is wider than 7 bits.
803 lex_15_bit_offset (bool *long_displacement
, expressionS
*exp
)
805 char *ilp
= input_line_pointer
;
808 if (lex_offset (&val
))
810 exp
->X_op
= O_absent
;
811 exp
->X_add_number
= val
;
813 else if (lex_expression (exp
))
815 if (exp
->X_op
== O_constant
)
817 val
= exp
->X_add_number
;
821 /* If a symbol was parsed we don't know the displacement.
822 We have to assume it is long, and relax it later if possible. */
823 *long_displacement
= true;
829 exp
->X_op
= O_absent
;
833 if (val
> 0x3FFF || val
< -0x4000)
835 as_fatal (_("Offset is outside of 15 bit range"));
839 *long_displacement
= (val
> 63 || val
< -64);
844 fail_line_pointer
= input_line_pointer
;
845 input_line_pointer
= ilp
;
850 emit_15_bit_offset (char *f
, int where
, expressionS
*exp
)
853 if (exp
->X_op
!= O_absent
&& exp
->X_op
!= O_constant
)
855 exp
->X_add_number
+= where
;
856 fixS
*fix
= fix_new_exp (frag_now
,
857 f
- frag_now
->fr_literal
,
862 fix
->fx_addnumber
= where
- 2;
866 long val
= exp
->X_add_number
;
867 bool long_displacement
= (val
> 63 || val
< -64);
868 if (long_displacement
)
873 number_to_chars_bigendian (f
++, val
, long_displacement
? 2 : 1);
878 rel (const struct instruction
*insn
)
880 bool long_displacement
;
883 if (! lex_15_bit_offset (&long_displacement
, &exp
))
886 char *f
= s12z_new_insn (long_displacement
? 3 : 2);
887 number_to_chars_bigendian (f
++, insn
->opc
, 1);
888 emit_15_bit_offset (f
, 3, &exp
);
893 reg_inh (const struct instruction
*insn
)
896 if (lex_reg_name (REG_BIT_Dn
, ®
))
898 char *f
= s12z_new_insn (insn
->page
);
900 number_to_chars_bigendian (f
++, PAGE2_PREBYTE
, 1);
902 number_to_chars_bigendian (f
++, insn
->opc
+ reg
, 1);
910 /* Special case for CLR X and CLR Y */
912 clr_xy (const struct instruction
*insn ATTRIBUTE_UNUSED
)
915 if (lex_reg_name (REG_BIT_XY
, ®
))
917 char *f
= s12z_new_insn (1);
918 number_to_chars_bigendian (f
, 0x9a + reg
- REG_X
, 1);
925 /* Some instructions have a suffix like ".l", ".b", ".w" etc
926 which indicates the size of the operands. */
928 size_from_suffix (const struct instruction
*insn
, int idx
)
930 const char *dot
= strchr (insn
->name
, '.');
936 switch (dot
[1 + idx
])
951 as_fatal (_("Bad size"));
958 mul_reg_reg_reg (const struct instruction
*insn
)
960 char *ilp
= input_line_pointer
;
963 if (!lex_reg_name (REG_BIT_Dn
, &Dd
))
966 if (!lex_match (','))
970 if (!lex_reg_name (REG_BIT_Dn
, &Dj
))
973 if (!lex_match (','))
977 if (!lex_reg_name (REG_BIT_Dn
, &Dk
))
980 char *f
= s12z_new_insn (insn
->page
+ 1);
982 number_to_chars_bigendian (f
++, PAGE2_PREBYTE
, 1);
984 number_to_chars_bigendian (f
++, insn
->opc
+ Dd
, 1);
985 const char *dot
= strchrnul (insn
->name
, '.');
996 as_fatal (_("BAD MUL"));
1003 number_to_chars_bigendian (f
++, mb
, 1);
1008 fail_line_pointer
= input_line_pointer
;
1009 input_line_pointer
= ilp
;
1015 mul_reg_reg_imm (const struct instruction
*insn
)
1017 char *ilp
= input_line_pointer
;
1020 if (!lex_reg_name (REG_BIT_Dn
, &Dd
))
1023 if (!lex_match (','))
1027 if (!lex_reg_name (REG_BIT_Dn
, &Dj
))
1030 if (!lex_match (','))
1034 if (!lex_imm (&imm
))
1038 int size
= size_from_suffix (insn
, 0);
1040 char *f
= s12z_new_insn (insn
->page
+ 1 + size
);
1041 if (insn
->page
== 2)
1042 number_to_chars_bigendian (f
++, PAGE2_PREBYTE
, 1);
1044 number_to_chars_bigendian (f
++, insn
->opc
+ Dd
, 1);
1046 const char *dot
= strchrnul (insn
->name
, '.');
1056 as_fatal (_("BAD MUL"));
1063 number_to_chars_bigendian (f
++, mb
, 1);
1064 number_to_chars_bigendian (f
++, imm
, size
);
1069 fail_line_pointer
= input_line_pointer
;
1070 input_line_pointer
= ilp
;
1076 mul_reg_reg_opr (const struct instruction
*insn
)
1078 char *ilp
= input_line_pointer
;
1081 if (!lex_reg_name (REG_BIT_Dn
, &Dd
))
1084 if (!lex_match (','))
1088 if (!lex_reg_name (REG_BIT_Dn
, &Dj
))
1091 if (!lex_match (','))
1097 if (!lex_opr (buffer
, &n_bytes
, &exp
))
1100 int size
= size_from_suffix (insn
, 0);
1102 char *f
= s12z_new_insn (insn
->page
+ 1 + n_bytes
);
1103 if (insn
->page
== 2)
1104 number_to_chars_bigendian (f
++, PAGE2_PREBYTE
, 1);
1106 number_to_chars_bigendian (f
++, insn
->opc
+ Dd
, 1);
1108 const char *dot
= strchrnul (insn
->name
, '.');
1118 as_fatal (_("BAD MUL"));
1125 number_to_chars_bigendian (f
++, mb
, 1);
1127 emit_opr (f
, buffer
, n_bytes
, &exp
);
1132 fail_line_pointer
= input_line_pointer
;
1133 input_line_pointer
= ilp
;
1138 mul_reg_opr_opr (const struct instruction
*insn
)
1140 char *ilp
= input_line_pointer
;
1143 if (!lex_reg_name (REG_BIT_Dn
, &Dd
))
1146 if (!lex_match (','))
1152 if (!lex_opr (buffer1
, &n_bytes1
, &exp1
))
1155 if (!lex_match (','))
1161 if (!lex_opr (buffer2
, &n_bytes2
, &exp2
))
1164 int size1
= size_from_suffix (insn
, 0);
1165 int size2
= size_from_suffix (insn
, 1);
1167 char *f
= s12z_new_insn (insn
->page
+ 1 + n_bytes1
+ n_bytes2
);
1168 if (insn
->page
== 2)
1169 number_to_chars_bigendian (f
++, PAGE2_PREBYTE
, 1);
1171 number_to_chars_bigendian (f
++, insn
->opc
+ Dd
, 1);
1173 const char *dot
= strchrnul (insn
->name
, '.');
1183 as_fatal (_("BAD MUL"));
1187 mb
|= (size1
- 1) << 4;
1188 mb
|= (size2
- 1) << 2;
1189 number_to_chars_bigendian (f
++, mb
, 1);
1191 f
= emit_opr (f
, buffer1
, n_bytes1
, &exp1
);
1192 f
= emit_opr (f
, buffer2
, n_bytes2
, &exp2
);
1197 fail_line_pointer
= input_line_pointer
;
1198 input_line_pointer
= ilp
;
1203 #define REG_BIT_GRP0 \
1204 ((0x1U << REG_D2) | \
1205 (0x1U << REG_D3) | \
1206 (0x1U << REG_CCH) | \
1207 (0x1U << REG_CCL) | \
1208 (0x1U << REG_D0) | \
1211 #define REG_BIT_GRP1 \
1212 ((0x1U << REG_D4) | \
1213 (0x1U << REG_D5) | \
1214 (0x1U << REG_D6) | \
1215 (0x1U << REG_D7) | \
1219 static const uint8_t reg_map
[] =
1239 lex_reg_list (uint16_t grp
, uint16_t *reg_bits
)
1241 if (lex_match (','))
1244 if (!lex_reg_name (grp
, ®
))
1246 *reg_bits
|= 0x1u
<< reg
;
1247 lex_reg_list (grp
, reg_bits
);
1255 psh_pull (const struct instruction
*insn
)
1258 (0 == strcmp ("pul", insn
->name
)) ? 0x80: 0x00;
1260 if (lex_match_string ("all16b"))
1264 else if (lex_match_string ("all"))
1271 if (!lex_reg_name (REG_BIT_GRP1
| REG_BIT_GRP0
, ®1
))
1273 uint16_t admitted_group
= 0;
1275 if ((0x1U
<< reg1
) & REG_BIT_GRP1
)
1276 admitted_group
= REG_BIT_GRP1
;
1277 else if ((0x1U
<< reg1
) & REG_BIT_GRP0
)
1278 admitted_group
= REG_BIT_GRP0
;
1280 uint16_t reg_bits
= 0x1 << reg1
;
1281 if (!lex_reg_list (admitted_group
, ®_bits
))
1284 if (reg_bits
& REG_BIT_GRP1
)
1288 for (i
= 0; i
< 16; ++i
)
1290 if (reg_bits
& (0x1u
<< i
))
1295 char *f
= s12z_new_insn (2);
1296 number_to_chars_bigendian (f
++, insn
->opc
, 1);
1297 number_to_chars_bigendian (f
++, pb
, 1);
1301 fail_line_pointer
= input_line_pointer
;
1307 tfr (const struct instruction
*insn
)
1310 if (!lex_reg_name (~0, ®1
))
1313 if (!lex_match (','))
1317 if (!lex_reg_name (~0, ®2
))
1320 if ( ((0 == strcasecmp ("sex", insn
->name
))
1321 || (0 == strcasecmp ("zex", insn
->name
)))
1322 && (registers
[reg2
].bytes
<= registers
[reg1
].bytes
))
1323 as_warn (_("Source register for %s is no larger than the destination register"),
1326 char *f
= s12z_new_insn (1 + insn
->page
);
1327 if (insn
->page
== 2)
1328 number_to_chars_bigendian (f
++, PAGE2_PREBYTE
, 1);
1330 number_to_chars_bigendian (f
++, insn
->opc
, 1);
1331 number_to_chars_bigendian (f
++, reg1
<< 4 | reg2
, 1);
1336 fail_line_pointer
= input_line_pointer
;
1341 imm8 (const struct instruction
*insn
)
1344 if (! lex_imm (&imm
))
1346 if (imm
> 127 || imm
< -128)
1348 as_bad (_("Immediate value %ld is out of range for instruction %s"),
1352 char *f
= s12z_new_insn (2);
1353 number_to_chars_bigendian (f
++, insn
->opc
, 1);
1354 number_to_chars_bigendian (f
++, imm
, 1);
1360 reg_imm (const struct instruction
*insn
, int allowed_reg
)
1362 char *ilp
= input_line_pointer
;
1364 if (lex_reg_name (allowed_reg
, ®
))
1366 if (!lex_force_match (','))
1369 if (! lex_imm (&imm
))
1372 short size
= registers
[reg
].bytes
;
1373 char *f
= s12z_new_insn (insn
->page
+ size
);
1374 if (insn
->page
== 2)
1375 number_to_chars_bigendian (f
++, PAGE2_PREBYTE
, 1);
1377 number_to_chars_bigendian (f
++, insn
->opc
+ reg
, 1);
1378 number_to_chars_bigendian (f
++, imm
, size
);
1383 fail_line_pointer
= input_line_pointer
;
1384 input_line_pointer
= ilp
;
1390 regd_imm (const struct instruction
*insn
)
1392 return reg_imm (insn
, REG_BIT_Dn
);
1396 regdxy_imm (const struct instruction
*insn
)
1398 return reg_imm (insn
, REG_BIT_Dn
| REG_BIT_XY
);
1403 regs_imm (const struct instruction
*insn
)
1405 return reg_imm (insn
, 0x1U
<< REG_S
);
1409 trap_imm (const struct instruction
*insn ATTRIBUTE_UNUSED
)
1412 if (! lex_imm (&imm
))
1415 if (imm
< 0x92 || imm
> 0xFF ||
1416 (imm
>= 0xA0 && imm
<= 0xA7) ||
1417 (imm
>= 0xB0 && imm
<= 0xB7))
1419 as_bad (_("trap value %ld is not valid"), imm
);
1424 char *f
= s12z_new_insn (2);
1425 number_to_chars_bigendian (f
++, PAGE2_PREBYTE
, 1);
1426 number_to_chars_bigendian (f
++, imm
& 0xFF, 1);
1433 fail_line_pointer
= input_line_pointer
;
1439 /* Special one byte instruction CMP X, Y */
1441 regx_regy (const struct instruction
*insn
)
1444 if (lex_reg_name (0x1U
<< REG_X
, ®
))
1446 if (lex_force_match (','))
1448 if (lex_reg_name (0x1U
<< REG_Y
, ®
))
1450 char *f
= s12z_new_insn (1);
1451 number_to_chars_bigendian (f
, insn
->opc
, 1);
1459 /* Special one byte instruction SUB D6, X, Y */
1461 regd6_regx_regy (const struct instruction
*insn
)
1463 char *ilp
= input_line_pointer
;
1465 if (!lex_reg_name (0x1U
<< REG_D6
, ®
))
1468 if (!lex_match (','))
1471 if (!lex_reg_name (0x1U
<< REG_X
, ®
))
1474 if (!lex_match (','))
1477 if (!lex_reg_name (0x1U
<< REG_Y
, ®
))
1480 char *f
= s12z_new_insn (1);
1481 number_to_chars_bigendian (f
, insn
->opc
, 1);
1485 fail_line_pointer
= input_line_pointer
;
1486 input_line_pointer
= ilp
;
1490 /* Special one byte instruction SUB D6, Y, X */
1492 regd6_regy_regx (const struct instruction
*insn
)
1494 char *ilp
= input_line_pointer
;
1496 if (!lex_reg_name (0x1U
<< REG_D6
, ®
))
1499 if (!lex_match (','))
1502 if (!lex_reg_name (0x1U
<< REG_Y
, ®
))
1505 if (!lex_match (','))
1508 if (!lex_reg_name (0x1U
<< REG_X
, ®
))
1511 char *f
= s12z_new_insn (1);
1512 number_to_chars_bigendian (f
, insn
->opc
, 1);
1516 fail_line_pointer
= input_line_pointer
;
1517 input_line_pointer
= ilp
;
1522 reg_opr (const struct instruction
*insn
, int allowed_regs
)
1524 char *ilp
= input_line_pointer
;
1526 if (lex_reg_name (allowed_regs
, ®
))
1528 if (!lex_force_match (','))
1534 if (lex_opr (buffer
, &n_bytes
, &exp
))
1536 /* Large constant direct values are more efficiently encoded as ext24 mode.
1537 Otherwise a decision has to be deferred to a relax. */
1538 if (exp
.X_op
== O_constant
1539 && buffer
[0] == 0xFA
1540 && insn
->alt_opc
!= 0)
1542 char *f
= s12z_new_insn (4);
1544 /* I don't think there are any instances of page 2 opcodes in this case */
1545 gas_assert (insn
->page
== 1);
1547 number_to_chars_bigendian (f
++, insn
->alt_opc
+ reg
, 1);
1549 emit_ext24 (f
, exp
.X_add_number
);
1553 char *f
= s12z_new_insn (n_bytes
+ insn
->page
);
1555 if (insn
->page
== 2)
1556 number_to_chars_bigendian (f
++, PAGE2_PREBYTE
, 1);
1558 number_to_chars_bigendian (f
++, insn
->opc
+ reg
, 1);
1560 emit_opr (f
, buffer
, n_bytes
, &exp
);
1568 fail_line_pointer
= input_line_pointer
;
1569 input_line_pointer
= ilp
;
1575 regdxy_opr (const struct instruction
*insn
)
1577 return reg_opr (insn
, REG_BIT_Dn
| REG_BIT_XY
);
1581 regd_opr (const struct instruction
*insn
)
1583 return reg_opr (insn
, REG_BIT_Dn
);
1588 regs_opr (const struct instruction
*insn
)
1590 return reg_opr (insn
, 0x1U
<< REG_S
);
1594 imm_opr (const struct instruction
*insn
)
1596 char *ilp
= input_line_pointer
;
1598 if (!lex_imm (&imm
))
1601 if (!lex_match (','))
1607 if (!lex_opr (buffer
, &n_bytes
, &exp
))
1610 int size
= size_from_suffix (insn
, 0);
1611 char *f
= s12z_new_insn (1 + n_bytes
+ size
);
1612 number_to_chars_bigendian (f
++, insn
->opc
, 1);
1615 for (i
= 0; i
< size
; ++i
)
1616 number_to_chars_bigendian (f
++, imm
>> (CHAR_BIT
* (size
- i
- 1)), 1);
1618 emit_opr (f
, buffer
, n_bytes
, &exp
);
1623 fail_line_pointer
= input_line_pointer
;
1624 input_line_pointer
= ilp
;
1629 opr_opr (const struct instruction
*insn
)
1631 char *ilp
= input_line_pointer
;
1636 if (!lex_opr (buffer1
, &n_bytes1
, &exp1
))
1640 if (!lex_match (','))
1646 if (!lex_opr (buffer2
, &n_bytes2
, &exp2
))
1649 char *f
= s12z_new_insn (1 + n_bytes1
+ n_bytes2
);
1650 number_to_chars_bigendian (f
++, insn
->opc
, 1);
1652 f
= emit_opr (f
, buffer1
, n_bytes1
, &exp1
);
1653 f
= emit_opr (f
, buffer2
, n_bytes2
, &exp2
);
1658 fail_line_pointer
= input_line_pointer
;
1659 input_line_pointer
= ilp
;
1664 reg67sxy_opr (const struct instruction
*insn
)
1667 if (!lex_reg_name (REG_BIT_XYS
| (0x1U
<< REG_D6
) | (0x1U
<< REG_D7
), ®
))
1670 if (!lex_match (','))
1676 if (!lex_opr (buffer
, &n_bytes
, &exp
))
1679 char *f
= s12z_new_insn (1 + n_bytes
);
1680 number_to_chars_bigendian (f
++, insn
->opc
+ reg
- REG_D6
, 1);
1681 emit_opr (f
, buffer
, n_bytes
, &exp
);
1687 rotate (const struct instruction
*insn
, short dir
)
1692 if (lex_opr (buffer
, &n_bytes
, &exp
))
1694 char *f
= s12z_new_insn (n_bytes
+ 2);
1695 number_to_chars_bigendian (f
++, insn
->opc
, 1);
1696 int size
= size_from_suffix (insn
, 0);
1703 number_to_chars_bigendian (f
++, sb
, 1);
1704 emit_opr (f
, buffer
, n_bytes
, &exp
);
1713 rol (const struct instruction
*insn
)
1715 return rotate (insn
, 1);
1719 ror (const struct instruction
*insn
)
1721 return rotate (insn
, 0);
1725 /* Shift instruction with a register operand and an immediate #1 or #2
1726 left = 1; right = 0;
1727 logical = 0; arithmetic = 1;
1730 lex_shift_reg_imm1 (const struct instruction
*insn
, short type
, short dir
)
1733 This function is highly unusual and a bit wierd!
1734 It first matches the input against a register {d0, d1, ... d7} followed by an immediate
1736 Then, it rewinds the input and parses it again as a OPR.
1738 char *ilp
= input_line_pointer
;
1741 if (!lex_reg_name (REG_BIT_Dn
, &Dd
))
1746 if (!lex_match (','))
1750 if (!lex_imm (&imm
))
1753 if (imm
!= 1 && imm
!= 2)
1755 input_line_pointer
= ilp
;
1757 /* Now parse the first operand again */
1763 if (!lex_opr (buffer
, &n_bytes
, &exp
))
1766 gas_assert (n_bytes
== 1);
1774 char *f
= s12z_new_insn (3);
1775 number_to_chars_bigendian (f
++, insn
->opc
, 1);
1776 number_to_chars_bigendian (f
++, sb
, 1);
1777 emit_opr (f
, buffer
, n_bytes
, &exp
);
1782 fail_line_pointer
= input_line_pointer
;
1783 input_line_pointer
= ilp
;
1787 /* Shift instruction with a register operand.
1788 left = 1; right = 0;
1789 logical = 0; arithmetic = 1; */
1791 lex_shift_reg (const struct instruction
*insn
, short type
, short dir
)
1794 if (!lex_reg_name (REG_BIT_Dn
, &Dd
))
1799 if (!lex_match (','))
1802 if (!lex_reg_name (REG_BIT_Dn
, &Ds
))
1807 if (!lex_match (','))
1815 if (lex_reg_name (REG_BIT_Dn
, &Dn
))
1817 char *f
= s12z_new_insn (3);
1818 number_to_chars_bigendian (f
++, insn
->opc
| Dd
, 1);
1819 number_to_chars_bigendian (f
++, sb
, 1);
1822 number_to_chars_bigendian (f
++, xb
, 1);
1826 else if (lex_imm (&imm
))
1828 if (imm
< 0 || imm
> 31)
1830 as_bad (_("Shift value should be in the range [0,31]"));
1835 if (imm
== 1 || imm
== 2)
1842 sb
|= (imm
& 0x01) << 3;
1845 char *f
= s12z_new_insn (n_bytes
);
1846 number_to_chars_bigendian (f
++, insn
->opc
| Dd
, 1);
1847 number_to_chars_bigendian (f
++, sb
, 1);
1852 number_to_chars_bigendian (f
++, xb
, 1);
1859 fail_line_pointer
= input_line_pointer
;
1864 impute_shift_dir_and_type (const struct instruction
*insn
, short *type
, short *dir
)
1868 switch (insn
->name
[0])
1877 as_fatal (_("Bad shift mode"));
1881 switch (insn
->name
[2])
1890 as_fatal (_("Bad shift *direction"));
1895 /* Shift instruction with a OPR operand */
1897 shift_two_operand (const struct instruction
*insn
)
1900 char *ilp
= input_line_pointer
;
1904 impute_shift_dir_and_type (insn
, &type
, &dir
);
1908 int size
= size_from_suffix (insn
, 0);
1914 if (!lex_opr (buffer
, &n_opr_bytes
, &exp
))
1917 if (!lex_match (','))
1921 if (!lex_imm (&imm
))
1924 if (imm
!= 1 && imm
!= 2)
1930 char *f
= s12z_new_insn (2 + n_opr_bytes
);
1931 number_to_chars_bigendian (f
++, insn
->opc
, 1);
1932 number_to_chars_bigendian (f
++, sb
, 1);
1933 emit_opr (f
, buffer
, n_opr_bytes
, &exp
);
1938 fail_line_pointer
= input_line_pointer
;
1939 input_line_pointer
= ilp
;
1943 /* Shift instruction with a OPR operand */
1945 shift_opr_imm (const struct instruction
*insn
)
1947 char *ilp
= input_line_pointer
;
1951 impute_shift_dir_and_type (insn
, &type
, &dir
);
1954 if (!lex_reg_name (REG_BIT_Dn
, &Dd
))
1957 if (!lex_match (','))
1966 if (!lex_opr (buffer1
, &n_opr_bytes1
, &exp1
))
1969 n_bytes
+= n_opr_bytes1
;
1970 if (!lex_match (','))
1974 int n_opr_bytes2
= 0;
1977 bool immediate
= false;
1982 else if (!lex_opr (buffer2
, &n_opr_bytes2
, &exp2
))
1987 int size
= size_from_suffix (insn
, 0);
1997 if (imm
== 2 || imm
== 1)
2012 n_bytes
+= n_opr_bytes2
;
2016 char *f
= s12z_new_insn (n_bytes
);
2017 number_to_chars_bigendian (f
++, insn
->opc
| Dd
, 1);
2018 number_to_chars_bigendian (f
++, sb
, 1);
2019 f
= emit_opr (f
, buffer1
, n_opr_bytes1
, &exp1
);
2022 if (imm
!= 1 && imm
!= 2)
2024 number_to_chars_bigendian (f
++, 0x70 | (imm
>> 1), 1);
2029 f
= emit_opr (f
, buffer2
, n_opr_bytes2
, &exp2
);
2035 fail_line_pointer
= input_line_pointer
;
2036 input_line_pointer
= ilp
;
2040 /* Shift instruction with a register operand */
2042 shift_reg (const struct instruction
*insn
)
2046 impute_shift_dir_and_type (insn
, &type
, &dir
);
2048 if (lex_shift_reg_imm1 (insn
, type
, dir
))
2051 return lex_shift_reg (insn
, type
, dir
);
2055 bm_regd_imm (const struct instruction
*insn
)
2057 char *ilp
= input_line_pointer
;
2059 if (!lex_reg_name (REG_BIT_Dn
, &Di
))
2062 if (!lex_match (','))
2066 if (!lex_imm (&imm
))
2070 uint8_t bm
= imm
<< 3;
2073 char *f
= s12z_new_insn (2);
2074 number_to_chars_bigendian (f
++, insn
->opc
, 1);
2075 number_to_chars_bigendian (f
++, bm
, 1);
2080 fail_line_pointer
= input_line_pointer
;
2081 input_line_pointer
= ilp
;
2086 bm_opr_reg (const struct instruction
*insn
)
2088 char *ilp
= input_line_pointer
;
2094 if (!lex_opr (buffer
, &n_opr_bytes
, &exp
))
2097 if (!lex_match (','))
2101 if (!lex_reg_name (REG_BIT_Dn
, &Dn
))
2104 uint8_t bm
= Dn
<< 4;
2105 int size
= size_from_suffix (insn
, 0);
2106 bm
|= (size
- 1) << 2;
2109 char *f
= s12z_new_insn (2 + n_opr_bytes
);
2110 number_to_chars_bigendian (f
++, insn
->opc
, 1);
2111 number_to_chars_bigendian (f
++, bm
, 1);
2113 emit_opr (f
, buffer
, n_opr_bytes
, &exp
);
2118 fail_line_pointer
= input_line_pointer
;
2119 input_line_pointer
= ilp
;
2125 bm_opr_imm (const struct instruction
*insn
)
2127 char *ilp
= input_line_pointer
;
2133 if (!lex_opr (buffer
, &n_opr_bytes
, &exp
))
2136 if (!lex_match (','))
2141 if (!lex_imm (&imm
))
2144 int size
= size_from_suffix (insn
, 0);
2146 if (imm
< 0 || imm
>= size
* 8)
2148 as_bad (_("Immediate operand %ld is inappropriate for size of instruction"), imm
);
2157 bm
|= (imm
& 0x07) << 4;
2161 char *f
= s12z_new_insn (2 + n_opr_bytes
);
2162 number_to_chars_bigendian (f
++, insn
->opc
, 1);
2163 number_to_chars_bigendian (f
++, bm
, 1);
2164 emit_opr (f
, buffer
, n_opr_bytes
, &exp
);
2169 fail_line_pointer
= input_line_pointer
;
2170 input_line_pointer
= ilp
;
2176 bm_regd_reg (const struct instruction
*insn
)
2178 char *ilp
= input_line_pointer
;
2180 if (!lex_reg_name (REG_BIT_Dn
, &Di
))
2183 if (!lex_match (','))
2187 if (!lex_reg_name (REG_BIT_Dn
, &Dn
))
2190 uint8_t bm
= Dn
<< 4;
2193 uint8_t xb
= Di
| 0xb8;
2195 char *f
= s12z_new_insn (3);
2196 number_to_chars_bigendian (f
++, insn
->opc
, 1);
2197 number_to_chars_bigendian (f
++, bm
, 1);
2198 number_to_chars_bigendian (f
++, xb
, 1);
2203 fail_line_pointer
= input_line_pointer
;
2204 input_line_pointer
= ilp
;
2213 bf_reg_opr_imm (const struct instruction
*insn
, short ie
)
2215 char *ilp
= input_line_pointer
;
2217 if (!lex_reg_name (REG_BIT_Dn
, &Dd
))
2220 if (!lex_match (','))
2227 if (!lex_opr (buffer
, &n_bytes
, &exp
))
2230 if (!lex_match (','))
2234 if (!lex_imm (&width
))
2237 if (width
< 0 || width
> 31)
2239 as_bad (_("Invalid width value for %s"), insn
->name
);
2243 if (!lex_match (':'))
2247 if (!lex_constant (&offset
))
2250 if (offset
< 0 || offset
> 31)
2252 as_bad (_("Invalid offset value for %s"), insn
->name
);
2256 uint8_t i1
= width
<< 5;
2259 int size
= size_from_suffix (insn
, 0);
2260 uint8_t bb
= ie
? 0x80 : 0x00;
2262 bb
|= (size
- 1) << 2;
2265 char *f
= s12z_new_insn (4 + n_bytes
);
2266 number_to_chars_bigendian (f
++, PAGE2_PREBYTE
, 1);
2267 number_to_chars_bigendian (f
++, 0x08 | Dd
, 1);
2268 number_to_chars_bigendian (f
++, bb
, 1);
2269 number_to_chars_bigendian (f
++, i1
, 1);
2271 emit_opr (f
, buffer
, n_bytes
, &exp
);
2276 fail_line_pointer
= input_line_pointer
;
2277 input_line_pointer
= ilp
;
2283 bf_opr_reg_imm (const struct instruction
*insn
, short ie
)
2285 char *ilp
= input_line_pointer
;
2289 if (!lex_opr (buffer
, &n_bytes
, &exp
))
2292 if (!lex_match (','))
2296 if (!lex_reg_name (REG_BIT_Dn
, &Ds
))
2299 if (!lex_match (','))
2303 if (!lex_imm (&width
))
2306 if (width
< 0 || width
> 31)
2308 as_bad (_("Invalid width value for %s"), insn
->name
);
2312 if (!lex_match (':'))
2316 if (!lex_constant (&offset
))
2319 if (offset
< 0 || offset
> 31)
2321 as_bad (_("Invalid offset value for %s"), insn
->name
);
2325 uint8_t i1
= width
<< 5;
2328 int size
= size_from_suffix (insn
, 0);
2329 uint8_t bb
= ie
? 0x80 : 0x00;
2331 bb
|= (size
- 1) << 2;
2334 char *f
= s12z_new_insn (4 + n_bytes
);
2335 number_to_chars_bigendian (f
++, PAGE2_PREBYTE
, 1);
2336 number_to_chars_bigendian (f
++, 0x08 | Ds
, 1);
2337 number_to_chars_bigendian (f
++, bb
, 1);
2338 number_to_chars_bigendian (f
++, i1
, 1);
2340 emit_opr (f
, buffer
, n_bytes
, &exp
);
2345 fail_line_pointer
= input_line_pointer
;
2346 input_line_pointer
= ilp
;
2353 bf_reg_reg_imm (const struct instruction
*insn
, short ie
)
2355 char *ilp
= input_line_pointer
;
2357 if (!lex_reg_name (REG_BIT_Dn
, &Dd
))
2360 if (!lex_match (','))
2364 if (!lex_reg_name (REG_BIT_Dn
, &Ds
))
2367 if (!lex_match (','))
2371 if (!lex_imm (&width
))
2374 if (width
< 0 || width
> 31)
2376 as_bad (_("Invalid width value for %s"), insn
->name
);
2380 if (!lex_match (':'))
2384 if (!lex_constant (&offset
))
2387 if (offset
< 0 || offset
> 31)
2389 as_bad (_("Invalid offset value for %s"), insn
->name
);
2393 uint8_t bb
= ie
? 0x80 : 0x00;
2398 uint8_t i1
= width
<< 5;
2401 char *f
= s12z_new_insn (4);
2402 number_to_chars_bigendian (f
++, PAGE2_PREBYTE
, 1);
2403 number_to_chars_bigendian (f
++, 0x08 | Dd
, 1);
2404 number_to_chars_bigendian (f
++, bb
, 1);
2405 number_to_chars_bigendian (f
++, i1
, 1);
2410 fail_line_pointer
= input_line_pointer
;
2411 input_line_pointer
= ilp
;
2416 bf_reg_reg_reg (const struct instruction
*insn ATTRIBUTE_UNUSED
, short ie
)
2418 char *ilp
= input_line_pointer
;
2420 if (!lex_reg_name (REG_BIT_Dn
, &Dd
))
2423 if (!lex_match (','))
2427 if (!lex_reg_name (REG_BIT_Dn
, &Ds
))
2430 if (!lex_match (','))
2434 if (!lex_reg_name ((0x01u
<< REG_D2
) |
2441 uint8_t bb
= ie
? 0x80 : 0x00;
2445 char *f
= s12z_new_insn (3);
2446 number_to_chars_bigendian (f
++, PAGE2_PREBYTE
, 1);
2447 number_to_chars_bigendian (f
++, 0x08 | Dd
, 1);
2448 number_to_chars_bigendian (f
++, bb
, 1);
2453 fail_line_pointer
= input_line_pointer
;
2454 input_line_pointer
= ilp
;
2459 bf_opr_reg_reg (const struct instruction
*insn
, short ie
)
2461 char *ilp
= input_line_pointer
;
2466 if (!lex_opr (buffer
, &n_bytes
, &exp
))
2469 if (!lex_match (','))
2474 if (!lex_reg_name (REG_BIT_Dn
, &Ds
))
2477 if (!lex_match (','))
2482 if (!lex_reg_name ((0x01u
<< REG_D2
) |
2489 int size
= size_from_suffix (insn
, 0);
2490 uint8_t bb
= ie
? 0x80 : 0x00;
2493 bb
|= (size
- 1) << 2;
2495 char *f
= s12z_new_insn (3 + n_bytes
);
2496 number_to_chars_bigendian (f
++, PAGE2_PREBYTE
, 1);
2497 number_to_chars_bigendian (f
++, 0x08 | Ds
, 1);
2498 number_to_chars_bigendian (f
++, bb
, 1);
2500 emit_opr (f
, buffer
, n_bytes
, &exp
);
2505 fail_line_pointer
= input_line_pointer
;
2506 input_line_pointer
= ilp
;
2512 bf_reg_opr_reg (const struct instruction
*insn
, short ie
)
2514 char *ilp
= input_line_pointer
;
2516 if (!lex_reg_name (REG_BIT_Dn
, &Dd
))
2519 if (!lex_match (','))
2526 if (!lex_opr (buffer
, &n_bytes
, &exp
))
2529 if (!lex_match (','))
2533 if (!lex_reg_name ((0x01u
<< REG_D2
) |
2540 int size
= size_from_suffix (insn
, 0);
2541 uint8_t bb
= ie
? 0x80 : 0x00;
2544 bb
|= (size
- 1) << 2;
2546 char *f
= s12z_new_insn (3 + n_bytes
);
2547 number_to_chars_bigendian (f
++, PAGE2_PREBYTE
, 1);
2548 number_to_chars_bigendian (f
++, 0x08 | Dd
, 1);
2549 number_to_chars_bigendian (f
++, bb
, 1);
2551 emit_opr (f
, buffer
, n_bytes
, &exp
);
2556 fail_line_pointer
= input_line_pointer
;
2557 input_line_pointer
= ilp
;
2564 bfe_reg_reg_reg (const struct instruction
*insn
)
2566 return bf_reg_reg_reg (insn
, 0);
2570 bfi_reg_reg_reg (const struct instruction
*insn
)
2572 return bf_reg_reg_reg (insn
, 1);
2576 bfe_reg_reg_imm (const struct instruction
*insn
)
2578 return bf_reg_reg_imm (insn
, 0);
2582 bfi_reg_reg_imm (const struct instruction
*insn
)
2584 return bf_reg_reg_imm (insn
, 1);
2589 bfe_reg_opr_reg (const struct instruction
*insn
)
2591 return bf_reg_opr_reg (insn
, 0);
2595 bfi_reg_opr_reg (const struct instruction
*insn
)
2597 return bf_reg_opr_reg (insn
, 1);
2602 bfe_opr_reg_reg (const struct instruction
*insn
)
2604 return bf_opr_reg_reg (insn
, 0);
2608 bfi_opr_reg_reg (const struct instruction
*insn
)
2610 return bf_opr_reg_reg (insn
, 1);
2614 bfe_reg_opr_imm (const struct instruction
*insn
)
2616 return bf_reg_opr_imm (insn
, 0);
2620 bfi_reg_opr_imm (const struct instruction
*insn
)
2622 return bf_reg_opr_imm (insn
, 1);
2626 bfe_opr_reg_imm (const struct instruction
*insn
)
2628 return bf_opr_reg_imm (insn
, 0);
2632 bfi_opr_reg_imm (const struct instruction
*insn
)
2634 return bf_opr_reg_imm (insn
, 1);
2641 tb_reg_rel (const struct instruction
*insn
)
2643 char *ilp
= input_line_pointer
;
2646 if (!lex_reg_name (REG_BIT_Dn
| REG_BIT_XY
, ®
))
2649 if (!lex_match (','))
2652 bool long_displacement
;
2654 if (! lex_15_bit_offset (&long_displacement
, &exp
))
2658 if (reg
== REG_X
|| reg
== REG_Y
)
2669 if (0 == strncmp (insn
->name
+ 2, "ne", 2))
2671 else if (0 == strncmp (insn
->name
+ 2, "eq", 2))
2673 else if (0 == strncmp (insn
->name
+ 2, "pl", 2))
2675 else if (0 == strncmp (insn
->name
+ 2, "mi", 2))
2677 else if (0 == strncmp (insn
->name
+ 2, "gt", 2))
2679 else if (0 == strncmp (insn
->name
+ 2, "le", 2))
2682 switch (insn
->name
[0])
2694 char *f
= s12z_new_insn (long_displacement
? 4 : 3);
2695 number_to_chars_bigendian (f
++, insn
->opc
, 1);
2696 number_to_chars_bigendian (f
++, lb
, 1);
2698 emit_15_bit_offset (f
, 4, &exp
);
2703 fail_line_pointer
= input_line_pointer
;
2704 input_line_pointer
= ilp
;
2710 tb_opr_rel (const struct instruction
*insn
)
2712 char *ilp
= input_line_pointer
;
2717 if (!lex_opr (buffer
, &n_bytes
, &exp
))
2720 if (!lex_match (','))
2723 bool long_displacement
;
2725 if (! lex_15_bit_offset (&long_displacement
, &exp2
))
2730 if (0 == strncmp (insn
->name
+ 2, "ne", 2))
2732 else if (0 == strncmp (insn
->name
+ 2, "eq", 2))
2734 else if (0 == strncmp (insn
->name
+ 2, "pl", 2))
2736 else if (0 == strncmp (insn
->name
+ 2, "mi", 2))
2738 else if (0 == strncmp (insn
->name
+ 2, "gt", 2))
2740 else if (0 == strncmp (insn
->name
+ 2, "le", 2))
2743 switch (insn
->name
[0])
2755 int size
= size_from_suffix (insn
, 0);
2759 char *f
= s12z_new_insn (n_bytes
+ (long_displacement
? 4 : 3));
2760 number_to_chars_bigendian (f
++, insn
->opc
, 1);
2761 number_to_chars_bigendian (f
++, lb
, 1);
2762 f
= emit_opr (f
, buffer
, n_bytes
, &exp
);
2764 emit_15_bit_offset (f
, n_bytes
+ 4, &exp2
);
2769 fail_line_pointer
= input_line_pointer
;
2770 input_line_pointer
= ilp
;
2778 test_br_reg_reg_rel (const struct instruction
*insn
)
2780 char *ilp
= input_line_pointer
;
2783 if (!lex_reg_name (REG_BIT_Dn
, &Di
))
2786 if (!lex_match (','))
2791 if (!lex_reg_name (REG_BIT_Dn
, &Dn
))
2794 if (!lex_match (','))
2798 bool long_displacement
;
2800 if (! lex_15_bit_offset (&long_displacement
, &exp
))
2809 char *f
= s12z_new_insn (long_displacement
? 5 : 4);
2810 number_to_chars_bigendian (f
++, insn
->opc
, 1);
2811 number_to_chars_bigendian (f
++, bm
, 1);
2812 number_to_chars_bigendian (f
++, xb
, 1);
2814 emit_15_bit_offset (f
, 5, &exp
);
2819 fail_line_pointer
= input_line_pointer
;
2820 input_line_pointer
= ilp
;
2825 test_br_opr_reg_rel (const struct instruction
*insn
)
2827 char *ilp
= input_line_pointer
;
2832 if (!lex_opr (buffer
, &n_bytes
, &exp
))
2835 if (!lex_match (','))
2839 if (!lex_reg_name (REG_BIT_Dn
, &Dn
))
2842 if (!lex_match (','))
2847 int size
= size_from_suffix (insn
, 0);
2848 bm
|= (size
-1) << 2;
2850 bool long_displacement
;
2853 if (! lex_15_bit_offset (&long_displacement
, &exp2
))
2856 int n
= n_bytes
+ (long_displacement
? 4 : 3);
2857 char *f
= s12z_new_insn (n
);
2858 number_to_chars_bigendian (f
++, insn
->opc
, 1);
2859 number_to_chars_bigendian (f
++, bm
, 1);
2860 f
= emit_opr (f
, buffer
, n_bytes
, &exp
);
2862 emit_15_bit_offset (f
, n
, &exp2
);
2867 fail_line_pointer
= input_line_pointer
;
2868 input_line_pointer
= ilp
;
2874 test_br_opr_imm_rel (const struct instruction
*insn
)
2876 char *ilp
= input_line_pointer
;
2881 if (!lex_opr (buffer
, &n_bytes
, &exp
))
2884 if (!lex_match (','))
2888 if (!lex_imm (&imm
))
2891 if (imm
< 0 || imm
> 31)
2894 if (!lex_match (','))
2897 bool long_displacement
;
2899 if (! lex_15_bit_offset (&long_displacement
, &exp2
))
2902 int size
= size_from_suffix (insn
, 0);
2905 bm
|= (imm
& 0x07) << 4;
2906 bm
|= (imm
>> 3) & 0x03;
2912 char *f
= s12z_new_insn (n_bytes
+ (long_displacement
? 4 : 3));
2913 number_to_chars_bigendian (f
++, insn
->opc
, 1);
2914 number_to_chars_bigendian (f
++, bm
, 1);
2915 f
= emit_opr (f
, buffer
, n_bytes
, &exp
);
2917 emit_15_bit_offset (f
, n_bytes
+ 4, &exp2
);
2922 fail_line_pointer
= input_line_pointer
;
2923 input_line_pointer
= ilp
;
2929 test_br_reg_imm_rel (const struct instruction
*insn
)
2931 char *ilp
= input_line_pointer
;
2934 if (!lex_reg_name (REG_BIT_Dn
, &Di
))
2937 if (!lex_match (','))
2941 if (!lex_imm (&imm
))
2944 if (imm
< 0 || imm
> 31)
2948 if (!lex_match (','))
2951 bool long_displacement
;
2953 if (! lex_15_bit_offset (&long_displacement
, &exp
))
2959 char *f
= s12z_new_insn (long_displacement
? 4 : 3);
2960 number_to_chars_bigendian (f
++, insn
->opc
, 1);
2961 number_to_chars_bigendian (f
++, bm
, 1);
2963 emit_15_bit_offset (f
, 4, &exp
);
2968 fail_line_pointer
= input_line_pointer
;
2969 input_line_pointer
= ilp
;
2976 static const struct instruction opcodes
[] = {
2977 {"bgnd", 1, 0x00, no_operands
, 0},
2978 {"nop", 1, 0x01, no_operands
, 0},
2980 {"brclr", 1, 0x02, test_br_reg_reg_rel
, 0},
2981 {"brset", 1, 0x03, test_br_reg_reg_rel
, 0},
2983 {"brclr", 1, 0x02, test_br_reg_imm_rel
, 0},
2984 {"brset", 1, 0x03, test_br_reg_imm_rel
, 0},
2986 {"brclr.b", 1, 0x02, test_br_opr_reg_rel
, 0},
2987 {"brclr.w", 1, 0x02, test_br_opr_reg_rel
, 0},
2988 {"brclr.l", 1, 0x02, test_br_opr_reg_rel
, 0},
2990 {"brset.b", 1, 0x03, test_br_opr_reg_rel
, 0},
2991 {"brset.w", 1, 0x03, test_br_opr_reg_rel
, 0},
2992 {"brset.l", 1, 0x03, test_br_opr_reg_rel
, 0},
2994 {"brclr.b", 1, 0x02, test_br_opr_imm_rel
, 0},
2995 {"brclr.w", 1, 0x02, test_br_opr_imm_rel
, 0},
2996 {"brclr.l", 1, 0x02, test_br_opr_imm_rel
, 0},
2998 {"brset.b", 1, 0x03, test_br_opr_imm_rel
, 0},
2999 {"brset.w", 1, 0x03, test_br_opr_imm_rel
, 0},
3000 {"brset.l", 1, 0x03, test_br_opr_imm_rel
, 0},
3002 {"psh", 1, 0x04, psh_pull
, 0},
3003 {"pul", 1, 0x04, psh_pull
, 0},
3005 {"rts", 1, 0x05, no_operands
, 0},
3006 {"lea", 1, 0x06, reg67sxy_opr
, 0},
3008 {"dbne", 1, 0x0b, tb_reg_rel
, 0},
3009 {"dbeq", 1, 0x0b, tb_reg_rel
, 0},
3010 {"dbpl", 1, 0x0b, tb_reg_rel
, 0},
3011 {"dbmi", 1, 0x0b, tb_reg_rel
, 0},
3012 {"dbgt", 1, 0x0b, tb_reg_rel
, 0},
3013 {"dble", 1, 0x0b, tb_reg_rel
, 0},
3015 {"dbne.b", 1, 0x0b, tb_opr_rel
, 0},
3016 {"dbeq.b", 1, 0x0b, tb_opr_rel
, 0},
3017 {"dbpl.b", 1, 0x0b, tb_opr_rel
, 0},
3018 {"dbmi.b", 1, 0x0b, tb_opr_rel
, 0},
3019 {"dbgt.b", 1, 0x0b, tb_opr_rel
, 0},
3020 {"dble.b", 1, 0x0b, tb_opr_rel
, 0},
3022 {"dbne.w", 1, 0x0b, tb_opr_rel
, 0},
3023 {"dbeq.w", 1, 0x0b, tb_opr_rel
, 0},
3024 {"dbpl.w", 1, 0x0b, tb_opr_rel
, 0},
3025 {"dbmi.w", 1, 0x0b, tb_opr_rel
, 0},
3026 {"dbgt.w", 1, 0x0b, tb_opr_rel
, 0},
3027 {"dble.w", 1, 0x0b, tb_opr_rel
, 0},
3029 {"dbne.p", 1, 0x0b, tb_opr_rel
, 0},
3030 {"dbeq.p", 1, 0x0b, tb_opr_rel
, 0},
3031 {"dbpl.p", 1, 0x0b, tb_opr_rel
, 0},
3032 {"dbmi.p", 1, 0x0b, tb_opr_rel
, 0},
3033 {"dbgt.p", 1, 0x0b, tb_opr_rel
, 0},
3034 {"dble.p", 1, 0x0b, tb_opr_rel
, 0},
3036 {"dbne.l", 1, 0x0b, tb_opr_rel
, 0},
3037 {"dbeq.l", 1, 0x0b, tb_opr_rel
, 0},
3038 {"dbpl.l", 1, 0x0b, tb_opr_rel
, 0},
3039 {"dbmi.l", 1, 0x0b, tb_opr_rel
, 0},
3040 {"dbgt.l", 1, 0x0b, tb_opr_rel
, 0},
3041 {"dble.l", 1, 0x0b, tb_opr_rel
, 0},
3043 {"tbne", 1, 0x0b, tb_reg_rel
, 0},
3044 {"tbeq", 1, 0x0b, tb_reg_rel
, 0},
3045 {"tbpl", 1, 0x0b, tb_reg_rel
, 0},
3046 {"tbmi", 1, 0x0b, tb_reg_rel
, 0},
3047 {"tbgt", 1, 0x0b, tb_reg_rel
, 0},
3048 {"tble", 1, 0x0b, tb_reg_rel
, 0},
3050 {"tbne.b", 1, 0x0b, tb_opr_rel
, 0},
3051 {"tbeq.b", 1, 0x0b, tb_opr_rel
, 0},
3052 {"tbpl.b", 1, 0x0b, tb_opr_rel
, 0},
3053 {"tbmi.b", 1, 0x0b, tb_opr_rel
, 0},
3054 {"tbgt.b", 1, 0x0b, tb_opr_rel
, 0},
3055 {"tble.b", 1, 0x0b, tb_opr_rel
, 0},
3057 {"tbne.w", 1, 0x0b, tb_opr_rel
, 0},
3058 {"tbeq.w", 1, 0x0b, tb_opr_rel
, 0},
3059 {"tbpl.w", 1, 0x0b, tb_opr_rel
, 0},
3060 {"tbmi.w", 1, 0x0b, tb_opr_rel
, 0},
3061 {"tbgt.w", 1, 0x0b, tb_opr_rel
, 0},
3062 {"tble.w", 1, 0x0b, tb_opr_rel
, 0},
3064 {"tbne.p", 1, 0x0b, tb_opr_rel
, 0},
3065 {"tbeq.p", 1, 0x0b, tb_opr_rel
, 0},
3066 {"tbpl.p", 1, 0x0b, tb_opr_rel
, 0},
3067 {"tbmi.p", 1, 0x0b, tb_opr_rel
, 0},
3068 {"tbgt.p", 1, 0x0b, tb_opr_rel
, 0},
3069 {"tble.p", 1, 0x0b, tb_opr_rel
, 0},
3071 {"tbne.l", 1, 0x0b, tb_opr_rel
, 0},
3072 {"tbeq.l", 1, 0x0b, tb_opr_rel
, 0},
3073 {"tbpl.l", 1, 0x0b, tb_opr_rel
, 0},
3074 {"tbmi.l", 1, 0x0b, tb_opr_rel
, 0},
3075 {"tbgt.l", 1, 0x0b, tb_opr_rel
, 0},
3076 {"tble.l", 1, 0x0b, tb_opr_rel
, 0},
3078 {"mov.b", 1, 0x0c, imm_opr
, 0},
3079 {"mov.w", 1, 0x0d, imm_opr
, 0},
3080 {"mov.p", 1, 0x0e, imm_opr
, 0},
3081 {"mov.l", 1, 0x0f, imm_opr
, 0},
3083 {"rol", 1, 0x10, rol
, 0},
3084 {"rol.b", 1, 0x10, rol
, 0},
3085 {"rol.w", 1, 0x10, rol
, 0},
3086 {"rol.p", 1, 0x10, rol
, 0},
3087 {"rol.l", 1, 0x10, rol
, 0},
3089 {"ror", 1, 0x10, ror
, 0},
3090 {"ror.b", 1, 0x10, ror
, 0},
3091 {"ror.w", 1, 0x10, ror
, 0},
3092 {"ror.p", 1, 0x10, ror
, 0},
3093 {"ror.l", 1, 0x10, ror
, 0},
3095 {"lsl", 1, 0x10, shift_reg
, 0},
3096 {"lsr", 1, 0x10, shift_reg
, 0},
3097 {"asl", 1, 0x10, shift_reg
, 0},
3098 {"asr", 1, 0x10, shift_reg
, 0},
3100 {"lsl.b", 1, 0x10, shift_two_operand
, 0},
3101 {"lsl.w", 1, 0x10, shift_two_operand
, 0},
3102 {"lsl.p", 1, 0x10, shift_two_operand
, 0},
3103 {"lsl.l", 1, 0x10, shift_two_operand
, 0},
3104 {"asl.b", 1, 0x10, shift_two_operand
, 0},
3105 {"asl.w", 1, 0x10, shift_two_operand
, 0},
3106 {"asl.p", 1, 0x10, shift_two_operand
, 0},
3107 {"asl.l", 1, 0x10, shift_two_operand
, 0},
3109 {"lsr.b", 1, 0x10, shift_two_operand
, 0},
3110 {"lsr.w", 1, 0x10, shift_two_operand
, 0},
3111 {"lsr.p", 1, 0x10, shift_two_operand
, 0},
3112 {"lsr.l", 1, 0x10, shift_two_operand
, 0},
3113 {"asr.b", 1, 0x10, shift_two_operand
, 0},
3114 {"asr.w", 1, 0x10, shift_two_operand
, 0},
3115 {"asr.p", 1, 0x10, shift_two_operand
, 0},
3116 {"asr.l", 1, 0x10, shift_two_operand
, 0},
3118 {"lsl.b", 1, 0x10, shift_opr_imm
, 0},
3119 {"lsl.w", 1, 0x10, shift_opr_imm
, 0},
3120 {"lsl.p", 1, 0x10, shift_opr_imm
, 0},
3121 {"lsl.l", 1, 0x10, shift_opr_imm
, 0},
3122 {"asl.b", 1, 0x10, shift_opr_imm
, 0},
3123 {"asl.w", 1, 0x10, shift_opr_imm
, 0},
3124 {"asl.p", 1, 0x10, shift_opr_imm
, 0},
3125 {"asl.l", 1, 0x10, shift_opr_imm
, 0},
3127 {"lsr.b", 1, 0x10, shift_opr_imm
, 0},
3128 {"lsr.w", 1, 0x10, shift_opr_imm
, 0},
3129 {"lsr.p", 1, 0x10, shift_opr_imm
, 0},
3130 {"lsr.l", 1, 0x10, shift_opr_imm
, 0},
3131 {"asr.b", 1, 0x10, shift_opr_imm
, 0},
3132 {"asr.w", 1, 0x10, shift_opr_imm
, 0},
3133 {"asr.p", 1, 0x10, shift_opr_imm
, 0},
3134 {"asr.l", 1, 0x10, shift_opr_imm
, 0},
3136 {"mov.b", 1, 0x1c, opr_opr
, 0},
3137 {"mov.w", 1, 0x1d, opr_opr
, 0},
3138 {"mov.p", 1, 0x1e, opr_opr
, 0},
3139 {"mov.l", 1, 0x1f, opr_opr
, 0},
3141 {"bra", 1, 0x20, rel
, 0},
3142 {"bsr", 1, 0x21, rel
, 0},
3143 {"bhi", 1, 0x22, rel
, 0},
3144 {"bls", 1, 0x23, rel
, 0},
3145 {"bcc", 1, 0x24, rel
, 0},
3146 {"bhs", 1, 0x24, rel
, 0}, /* Alias for bcc */
3147 {"bcs", 1, 0x25, rel
, 0},
3148 {"blo", 1, 0x25, rel
, 0}, /* Alias for bcs */
3149 {"bne", 1, 0x26, rel
, 0},
3150 {"beq", 1, 0x27, rel
, 0},
3151 {"bvc", 1, 0x28, rel
, 0},
3152 {"bvs", 1, 0x29, rel
, 0},
3153 {"bpl", 1, 0x2a, rel
, 0},
3154 {"bmi", 1, 0x2b, rel
, 0},
3155 {"bge", 1, 0x2c, rel
, 0},
3156 {"blt", 1, 0x2d, rel
, 0},
3157 {"bgt", 1, 0x2e, rel
, 0},
3158 {"ble", 1, 0x2f, rel
, 0},
3160 {"inc", 1, 0x30, reg_inh
, 0},
3161 {"clr", 1, 0x38, reg_inh
, 0},
3162 {"dec", 1, 0x40, reg_inh
, 0},
3164 {"muls", 1, 0x48, mul_reg_reg_reg
, 0},
3165 {"mulu", 1, 0x48, mul_reg_reg_reg
, 0},
3167 {"muls.b", 1, 0x48, mul_reg_reg_opr
, 0},
3168 {"muls.w", 1, 0x48, mul_reg_reg_opr
, 0},
3169 {"muls.l", 1, 0x48, mul_reg_reg_opr
, 0},
3171 {"mulu.b", 1, 0x48, mul_reg_reg_opr
, 0},
3172 {"mulu.w", 1, 0x48, mul_reg_reg_opr
, 0},
3173 {"mulu.l", 1, 0x48, mul_reg_reg_opr
, 0},
3175 {"muls.b", 1, 0x48, mul_reg_reg_imm
, 0},
3176 {"muls.w", 1, 0x48, mul_reg_reg_imm
, 0},
3177 {"muls.l", 1, 0x48, mul_reg_reg_imm
, 0},
3179 {"mulu.b", 1, 0x48, mul_reg_reg_imm
, 0},
3180 {"mulu.w", 1, 0x48, mul_reg_reg_imm
, 0},
3181 {"mulu.l", 1, 0x48, mul_reg_reg_imm
, 0},
3183 {"muls.bb", 1, 0x48, mul_reg_opr_opr
, 0},
3184 {"muls.bw", 1, 0x48, mul_reg_opr_opr
, 0},
3185 {"muls.bp", 1, 0x48, mul_reg_opr_opr
, 0},
3186 {"muls.bl", 1, 0x48, mul_reg_opr_opr
, 0},
3188 {"muls.wb", 1, 0x48, mul_reg_opr_opr
, 0},
3189 {"muls.ww", 1, 0x48, mul_reg_opr_opr
, 0},
3190 {"muls.wp", 1, 0x48, mul_reg_opr_opr
, 0},
3191 {"muls.wl", 1, 0x48, mul_reg_opr_opr
, 0},
3193 {"muls.pb", 1, 0x48, mul_reg_opr_opr
, 0},
3194 {"muls.pw", 1, 0x48, mul_reg_opr_opr
, 0},
3195 {"muls.pp", 1, 0x48, mul_reg_opr_opr
, 0},
3196 {"muls.pl", 1, 0x48, mul_reg_opr_opr
, 0},
3198 {"muls.lb", 1, 0x48, mul_reg_opr_opr
, 0},
3199 {"muls.lw", 1, 0x48, mul_reg_opr_opr
, 0},
3200 {"muls.lp", 1, 0x48, mul_reg_opr_opr
, 0},
3201 {"muls.ll", 1, 0x48, mul_reg_opr_opr
, 0},
3203 {"mulu.bb", 1, 0x48, mul_reg_opr_opr
, 0},
3204 {"mulu.bw", 1, 0x48, mul_reg_opr_opr
, 0},
3205 {"mulu.bp", 1, 0x48, mul_reg_opr_opr
, 0},
3206 {"mulu.bl", 1, 0x48, mul_reg_opr_opr
, 0},
3208 {"mulu.wb", 1, 0x48, mul_reg_opr_opr
, 0},
3209 {"mulu.ww", 1, 0x48, mul_reg_opr_opr
, 0},
3210 {"mulu.wp", 1, 0x48, mul_reg_opr_opr
, 0},
3211 {"mulu.wl", 1, 0x48, mul_reg_opr_opr
, 0},
3213 {"mulu.pb", 1, 0x48, mul_reg_opr_opr
, 0},
3214 {"mulu.pw", 1, 0x48, mul_reg_opr_opr
, 0},
3215 {"mulu.pp", 1, 0x48, mul_reg_opr_opr
, 0},
3216 {"mulu.pl", 1, 0x48, mul_reg_opr_opr
, 0},
3218 {"mulu.lb", 1, 0x48, mul_reg_opr_opr
, 0},
3219 {"mulu.lw", 1, 0x48, mul_reg_opr_opr
, 0},
3220 {"mulu.lp", 1, 0x48, mul_reg_opr_opr
, 0},
3221 {"mulu.ll", 1, 0x48, mul_reg_opr_opr
, 0},
3223 {"add", 1, 0x50, regd_imm
, 0},
3224 {"and", 1, 0x58, regd_imm
, 0},
3226 {"add", 1, 0x60, regd_opr
, 0},
3227 {"and", 1, 0x68, regd_opr
, 0},
3229 {"sub", 1, 0x70, regd_imm
, 0},
3230 {"or", 1, 0x78, regd_imm
, 0},
3232 {"sub", 1, 0x80, regd_opr
, 0},
3233 {"or", 1, 0x88, regd_opr
, 0},
3235 {"ld", 1, 0x90, regdxy_imm
, 0},
3237 {"clr", 1, 0x9a, clr_xy
, 0},
3238 {"tfr", 1, 0x9e, tfr
, 0},
3239 {"zex", 1, 0x9e, tfr
, 0},
3241 {"ld", 1, 0xa0, regdxy_opr
, 0xb0},
3243 {"jmp", 1, 0xaa, opr
, 0xba},
3244 {"jsr", 1, 0xab, opr
, 0xbb},
3246 {"exg", 1, 0xae, tfr
, 0},
3247 {"sex", 1, 0xae, tfr
, 0},
3249 {"st", 1, 0xc0, regdxy_opr
, 0xd0},
3251 {"andcc", 1, 0xce, imm8
, 0},
3252 {"orcc", 1, 0xde, imm8
, 0},
3254 {"inc.b", 1, 0x9c, opr
, 0},
3255 {"inc.w", 1, 0x9d, opr
, 0},
3256 {"inc.l", 1, 0x9f, opr
, 0},
3258 {"dec.b", 1, 0xac, opr
, 0},
3259 {"dec.w", 1, 0xad, opr
, 0},
3260 {"dec.l", 1, 0xaf, opr
, 0},
3262 {"clr.b", 1, 0xbc, opr
, 0},
3263 {"clr.w", 1, 0xbd, opr
, 0},
3264 {"clr.p", 1, 0xbe, opr
, 0},
3265 {"clr.l", 1, 0xbf, opr
, 0},
3267 {"com.b", 1, 0xcc, opr
, 0},
3268 {"com.w", 1, 0xcd, opr
, 0},
3269 {"com.l", 1, 0xcf, opr
, 0},
3271 {"neg.b", 1, 0xdc, opr
, 0},
3272 {"neg.w", 1, 0xdd, opr
, 0},
3273 {"neg.l", 1, 0xdf, opr
, 0},
3275 {"bclr", 1, 0xec, bm_regd_imm
, 0},
3276 {"bset", 1, 0xed, bm_regd_imm
, 0},
3277 {"btgl", 1, 0xee, bm_regd_imm
, 0},
3279 {"bclr", 1, 0xec, bm_regd_reg
, 0},
3280 {"bset", 1, 0xed, bm_regd_reg
, 0},
3281 {"btgl", 1, 0xee, bm_regd_reg
, 0},
3283 {"bclr.b", 1, 0xec, bm_opr_imm
, 0},
3284 {"bclr.w", 1, 0xec, bm_opr_imm
, 0},
3285 {"bclr.l", 1, 0xec, bm_opr_imm
, 0},
3287 {"bset.b", 1, 0xed, bm_opr_imm
, 0},
3288 {"bset.w", 1, 0xed, bm_opr_imm
, 0},
3289 {"bset.l", 1, 0xed, bm_opr_imm
, 0},
3291 {"btgl.b", 1, 0xee, bm_opr_imm
, 0},
3292 {"btgl.w", 1, 0xee, bm_opr_imm
, 0},
3293 {"btgl.l", 1, 0xee, bm_opr_imm
, 0},
3295 {"bclr.b", 1, 0xec, bm_opr_reg
, 0},
3296 {"bclr.w", 1, 0xec, bm_opr_reg
, 0},
3297 {"bclr.l", 1, 0xec, bm_opr_reg
, 0},
3299 {"bset.b", 1, 0xed, bm_opr_reg
, 0},
3300 {"bset.w", 1, 0xed, bm_opr_reg
, 0},
3301 {"bset.l", 1, 0xed, bm_opr_reg
, 0},
3303 {"btgl.b", 1, 0xee, bm_opr_reg
, 0},
3304 {"btgl.w", 1, 0xee, bm_opr_reg
, 0},
3305 {"btgl.l", 1, 0xee, bm_opr_reg
, 0},
3307 {"cmp", 1, 0xe0, regdxy_imm
, 0},
3308 {"cmp", 1, 0xf0, regdxy_opr
, 0},
3310 {"cmp", 1, 0xfc, regx_regy
, 0},
3311 {"sub", 1, 0xfd, regd6_regx_regy
, 0},
3312 {"sub", 1, 0xfe, regd6_regy_regx
, 0},
3314 {"swi", 1, 0xff, no_operands
, 0},
3318 /* The -10 below is a kludge. The opcode is in fact 0x00 */
3319 {"ld", 2, -10, regs_opr
, 0},
3321 /* The -9 below is a kludge. The opcode is in fact 0x01 */
3322 {"st", 2, -9, regs_opr
, 0},
3324 /* The -8 below is a kludge. The opcode is in fact 0x02 */
3325 {"cmp", 2, -8, regs_opr
, 0},
3327 /* The -7 below is a kludge. The opcode is in fact 0x03 */
3328 {"ld", 2, -7, regs_imm
, 0},
3330 /* The -6 below is a kludge. The opcode is in fact 0x04 */
3331 {"cmp", 2, -6, regs_imm
, 0},
3333 {"bfext", 2, 0x08, bfe_reg_reg_reg
, 0},
3334 {"bfext", 2, 0x08, bfe_reg_reg_imm
, 0},
3335 {"bfext.b", 2, 0x08, bfe_reg_opr_reg
, 0},
3336 {"bfext.w", 2, 0x08, bfe_reg_opr_reg
, 0},
3337 {"bfext.p", 2, 0x08, bfe_reg_opr_reg
, 0},
3338 {"bfext.l", 2, 0x08, bfe_reg_opr_reg
, 0},
3339 {"bfext.b", 2, 0x08, bfe_opr_reg_reg
, 0},
3340 {"bfext.w", 2, 0x08, bfe_opr_reg_reg
, 0},
3341 {"bfext.p", 2, 0x08, bfe_opr_reg_reg
, 0},
3342 {"bfext.l", 2, 0x08, bfe_opr_reg_reg
, 0},
3343 {"bfext.b", 2, 0x08, bfe_reg_opr_imm
, 0},
3344 {"bfext.w", 2, 0x08, bfe_reg_opr_imm
, 0},
3345 {"bfext.p", 2, 0x08, bfe_reg_opr_imm
, 0},
3346 {"bfext.l", 2, 0x08, bfe_reg_opr_imm
, 0},
3347 {"bfext.b", 2, 0x08, bfe_opr_reg_imm
, 0},
3348 {"bfext.w", 2, 0x08, bfe_opr_reg_imm
, 0},
3349 {"bfext.p", 2, 0x08, bfe_opr_reg_imm
, 0},
3350 {"bfext.l", 2, 0x08, bfe_opr_reg_imm
, 0},
3353 {"bfins", 2, 0x08, bfi_reg_reg_reg
, 0},
3354 {"bfins", 2, 0x08, bfi_reg_reg_imm
, 0},
3355 {"bfins.b", 2, 0x08, bfi_reg_opr_reg
, 0},
3356 {"bfins.w", 2, 0x08, bfi_reg_opr_reg
, 0},
3357 {"bfins.p", 2, 0x08, bfi_reg_opr_reg
, 0},
3358 {"bfins.l", 2, 0x08, bfi_reg_opr_reg
, 0},
3359 {"bfins.b", 2, 0x08, bfi_opr_reg_reg
, 0},
3360 {"bfins.w", 2, 0x08, bfi_opr_reg_reg
, 0},
3361 {"bfins.p", 2, 0x08, bfi_opr_reg_reg
, 0},
3362 {"bfins.l", 2, 0x08, bfi_opr_reg_reg
, 0},
3363 {"bfins.b", 2, 0x08, bfi_reg_opr_imm
, 0},
3364 {"bfins.w", 2, 0x08, bfi_reg_opr_imm
, 0},
3365 {"bfins.p", 2, 0x08, bfi_reg_opr_imm
, 0},
3366 {"bfins.l", 2, 0x08, bfi_reg_opr_imm
, 0},
3367 {"bfins.b", 2, 0x08, bfi_opr_reg_imm
, 0},
3368 {"bfins.w", 2, 0x08, bfi_opr_reg_imm
, 0},
3369 {"bfins.p", 2, 0x08, bfi_opr_reg_imm
, 0},
3370 {"bfins.l", 2, 0x08, bfi_opr_reg_imm
, 0},
3373 {"minu", 2, 0x10, regd_opr
, 0},
3374 {"maxu", 2, 0x18, regd_opr
, 0},
3375 {"mins", 2, 0x20, regd_opr
, 0},
3376 {"maxs", 2, 0x28, regd_opr
, 0},
3378 {"clb", 2, 0x91, tfr
, 0},
3380 {"trap", 2, 0x00, trap_imm
, 0},
3381 {"abs", 2, 0x40, reg_inh
, 0},
3382 {"sat", 2, 0xa0, reg_inh
, 0},
3384 {"rti", 2, 0x90, no_operands
, 0},
3385 {"stop", 2, 0x05, no_operands
, 0},
3386 {"wai", 2, 0x06, no_operands
, 0},
3387 {"sys", 2, 0x07, no_operands
, 0},
3389 {"bit", 2, 0x58, regd_imm
, 0},
3390 {"bit", 2, 0x68, regd_opr
, 0},
3392 {"adc", 2, 0x50, regd_imm
, 0},
3393 {"adc", 2, 0x60, regd_opr
, 0},
3395 {"sbc", 2, 0x70, regd_imm
, 0},
3396 {"eor", 2, 0x78, regd_imm
, 0},
3398 {"sbc", 2, 0x80, regd_opr
, 0},
3399 {"eor", 2, 0x88, regd_opr
, 0},
3401 {"divs", 2, 0x30, mul_reg_reg_reg
, 0},
3402 {"divu", 2, 0x30, mul_reg_reg_reg
, 0},
3404 {"divs.b", 2, 0x30, mul_reg_reg_opr
, 0},
3405 {"divs.w", 2, 0x30, mul_reg_reg_opr
, 0},
3406 {"divs.l", 2, 0x30, mul_reg_reg_opr
, 0},
3408 {"divu.b", 2, 0x30, mul_reg_reg_opr
, 0},
3409 {"divu.w", 2, 0x30, mul_reg_reg_opr
, 0},
3410 {"divu.l", 2, 0x30, mul_reg_reg_opr
, 0},
3412 {"divs.b", 2, 0x30, mul_reg_reg_imm
, 0},
3413 {"divs.w", 2, 0x30, mul_reg_reg_imm
, 0},
3414 {"divs.l", 2, 0x30, mul_reg_reg_imm
, 0},
3416 {"divu.b", 2, 0x30, mul_reg_reg_imm
, 0},
3417 {"divu.w", 2, 0x30, mul_reg_reg_imm
, 0},
3418 {"divu.l", 2, 0x30, mul_reg_reg_imm
, 0},
3420 {"divs.bb", 2, 0x30, mul_reg_opr_opr
, 0},
3421 {"divs.bw", 2, 0x30, mul_reg_opr_opr
, 0},
3422 {"divs.bp", 2, 0x30, mul_reg_opr_opr
, 0},
3423 {"divs.bl", 2, 0x30, mul_reg_opr_opr
, 0},
3425 {"divs.wb", 2, 0x30, mul_reg_opr_opr
, 0},
3426 {"divs.ww", 2, 0x30, mul_reg_opr_opr
, 0},
3427 {"divs.wp", 2, 0x30, mul_reg_opr_opr
, 0},
3428 {"divs.wl", 2, 0x30, mul_reg_opr_opr
, 0},
3430 {"divs.pb", 2, 0x30, mul_reg_opr_opr
, 0},
3431 {"divs.pw", 2, 0x30, mul_reg_opr_opr
, 0},
3432 {"divs.pp", 2, 0x30, mul_reg_opr_opr
, 0},
3433 {"divs.pl", 2, 0x30, mul_reg_opr_opr
, 0},
3435 {"divs.lb", 2, 0x30, mul_reg_opr_opr
, 0},
3436 {"divs.lw", 2, 0x30, mul_reg_opr_opr
, 0},
3437 {"divs.lp", 2, 0x30, mul_reg_opr_opr
, 0},
3438 {"divs.ll", 2, 0x30, mul_reg_opr_opr
, 0},
3440 {"divu.bb", 2, 0x30, mul_reg_opr_opr
, 0},
3441 {"divu.bw", 2, 0x30, mul_reg_opr_opr
, 0},
3442 {"divu.bp", 2, 0x30, mul_reg_opr_opr
, 0},
3443 {"divu.bl", 2, 0x30, mul_reg_opr_opr
, 0},
3445 {"divu.wb", 2, 0x30, mul_reg_opr_opr
, 0},
3446 {"divu.ww", 2, 0x30, mul_reg_opr_opr
, 0},
3447 {"divu.wp", 2, 0x30, mul_reg_opr_opr
, 0},
3448 {"divu.wl", 2, 0x30, mul_reg_opr_opr
, 0},
3450 {"divu.pb", 2, 0x30, mul_reg_opr_opr
, 0},
3451 {"divu.pw", 2, 0x30, mul_reg_opr_opr
, 0},
3452 {"divu.pp", 2, 0x30, mul_reg_opr_opr
, 0},
3453 {"divu.pl", 2, 0x30, mul_reg_opr_opr
, 0},
3455 {"divu.lb", 2, 0x30, mul_reg_opr_opr
, 0},
3456 {"divu.lw", 2, 0x30, mul_reg_opr_opr
, 0},
3457 {"divu.lp", 2, 0x30, mul_reg_opr_opr
, 0},
3458 {"divu.ll", 2, 0x30, mul_reg_opr_opr
, 0},
3462 {"qmuls", 2, 0xb0, mul_reg_reg_reg
, 0},
3463 {"qmulu", 2, 0xb0, mul_reg_reg_reg
, 0},
3465 {"qmuls.b", 2, 0xb0, mul_reg_reg_opr
, 0},
3466 {"qmuls.w", 2, 0xb0, mul_reg_reg_opr
, 0},
3467 {"qmuls.l", 2, 0xb0, mul_reg_reg_opr
, 0},
3469 {"qmulu.b", 2, 0xb0, mul_reg_reg_opr
, 0},
3470 {"qmulu.w", 2, 0xb0, mul_reg_reg_opr
, 0},
3471 {"qmulu.l", 2, 0xb0, mul_reg_reg_opr
, 0},
3473 {"qmuls.b", 2, 0xb0, mul_reg_reg_imm
, 0},
3474 {"qmuls.w", 2, 0xb0, mul_reg_reg_imm
, 0},
3475 {"qmuls.l", 2, 0xb0, mul_reg_reg_imm
, 0},
3477 {"qmulu.b", 2, 0xb0, mul_reg_reg_imm
, 0},
3478 {"qmulu.w", 2, 0xb0, mul_reg_reg_imm
, 0},
3479 {"qmulu.l", 2, 0xb0, mul_reg_reg_imm
, 0},
3481 {"qmuls.bb", 2, 0xb0, mul_reg_opr_opr
, 0},
3482 {"qmuls.bw", 2, 0xb0, mul_reg_opr_opr
, 0},
3483 {"qmuls.bp", 2, 0xb0, mul_reg_opr_opr
, 0},
3484 {"qmuls.bl", 2, 0xb0, mul_reg_opr_opr
, 0},
3486 {"qmuls.wb", 2, 0xb0, mul_reg_opr_opr
, 0},
3487 {"qmuls.ww", 2, 0xb0, mul_reg_opr_opr
, 0},
3488 {"qmuls.wp", 2, 0xb0, mul_reg_opr_opr
, 0},
3489 {"qmuls.wl", 2, 0xb0, mul_reg_opr_opr
, 0},
3491 {"qmuls.pb", 2, 0xb0, mul_reg_opr_opr
, 0},
3492 {"qmuls.pw", 2, 0xb0, mul_reg_opr_opr
, 0},
3493 {"qmuls.pp", 2, 0xb0, mul_reg_opr_opr
, 0},
3494 {"qmuls.pl", 2, 0xb0, mul_reg_opr_opr
, 0},
3496 {"qmuls.lb", 2, 0xb0, mul_reg_opr_opr
, 0},
3497 {"qmuls.lw", 2, 0xb0, mul_reg_opr_opr
, 0},
3498 {"qmuls.lp", 2, 0xb0, mul_reg_opr_opr
, 0},
3499 {"qmuls.ll", 2, 0xb0, mul_reg_opr_opr
, 0},
3501 {"qmulu.bb", 2, 0xb0, mul_reg_opr_opr
, 0},
3502 {"qmulu.bw", 2, 0xb0, mul_reg_opr_opr
, 0},
3503 {"qmulu.bp", 2, 0xb0, mul_reg_opr_opr
, 0},
3504 {"qmulu.bl", 2, 0xb0, mul_reg_opr_opr
, 0},
3506 {"qmulu.wb", 2, 0xb0, mul_reg_opr_opr
, 0},
3507 {"qmulu.ww", 2, 0xb0, mul_reg_opr_opr
, 0},
3508 {"qmulu.wp", 2, 0xb0, mul_reg_opr_opr
, 0},
3509 {"qmulu.wl", 2, 0xb0, mul_reg_opr_opr
, 0},
3511 {"qmulu.pb", 2, 0xb0, mul_reg_opr_opr
, 0},
3512 {"qmulu.pw", 2, 0xb0, mul_reg_opr_opr
, 0},
3513 {"qmulu.pp", 2, 0xb0, mul_reg_opr_opr
, 0},
3514 {"qmulu.pl", 2, 0xb0, mul_reg_opr_opr
, 0},
3516 {"qmulu.lb", 2, 0xb0, mul_reg_opr_opr
, 0},
3517 {"qmulu.lw", 2, 0xb0, mul_reg_opr_opr
, 0},
3518 {"qmulu.lp", 2, 0xb0, mul_reg_opr_opr
, 0},
3519 {"qmulu.ll", 2, 0xb0, mul_reg_opr_opr
, 0},
3524 {"macs", 2, 0x48, mul_reg_reg_reg
, 0},
3525 {"macu", 2, 0x48, mul_reg_reg_reg
, 0},
3527 {"macs.b", 2, 0x48, mul_reg_reg_opr
, 0},
3528 {"macs.w", 2, 0x48, mul_reg_reg_opr
, 0},
3529 {"macs.l", 2, 0x48, mul_reg_reg_opr
, 0},
3531 {"macu.b", 2, 0x48, mul_reg_reg_opr
, 0},
3532 {"macu.w", 2, 0x48, mul_reg_reg_opr
, 0},
3533 {"macu.l", 2, 0x48, mul_reg_reg_opr
, 0},
3535 {"macs.b", 2, 0x48, mul_reg_reg_imm
, 0},
3536 {"macs.w", 2, 0x48, mul_reg_reg_imm
, 0},
3537 {"macs.l", 2, 0x48, mul_reg_reg_imm
, 0},
3539 {"macu.b", 2, 0x48, mul_reg_reg_imm
, 0},
3540 {"macu.w", 2, 0x48, mul_reg_reg_imm
, 0},
3541 {"macu.l", 2, 0x48, mul_reg_reg_imm
, 0},
3543 {"macs.bb", 2, 0x48, mul_reg_opr_opr
, 0},
3544 {"macs.bw", 2, 0x48, mul_reg_opr_opr
, 0},
3545 {"macs.bp", 2, 0x48, mul_reg_opr_opr
, 0},
3546 {"macs.bl", 2, 0x48, mul_reg_opr_opr
, 0},
3548 {"macs.wb", 2, 0x48, mul_reg_opr_opr
, 0},
3549 {"macs.ww", 2, 0x48, mul_reg_opr_opr
, 0},
3550 {"macs.wp", 2, 0x48, mul_reg_opr_opr
, 0},
3551 {"macs.wl", 2, 0x48, mul_reg_opr_opr
, 0},
3553 {"macs.pb", 2, 0x48, mul_reg_opr_opr
, 0},
3554 {"macs.pw", 2, 0x48, mul_reg_opr_opr
, 0},
3555 {"macs.pp", 2, 0x48, mul_reg_opr_opr
, 0},
3556 {"macs.pl", 2, 0x48, mul_reg_opr_opr
, 0},
3558 {"macs.lb", 2, 0x48, mul_reg_opr_opr
, 0},
3559 {"macs.lw", 2, 0x48, mul_reg_opr_opr
, 0},
3560 {"macs.lp", 2, 0x48, mul_reg_opr_opr
, 0},
3561 {"macs.ll", 2, 0x48, mul_reg_opr_opr
, 0},
3563 {"macu.bb", 2, 0x48, mul_reg_opr_opr
, 0},
3564 {"macu.bw", 2, 0x48, mul_reg_opr_opr
, 0},
3565 {"macu.bp", 2, 0x48, mul_reg_opr_opr
, 0},
3566 {"macu.bl", 2, 0x48, mul_reg_opr_opr
, 0},
3568 {"macu.wb", 2, 0x48, mul_reg_opr_opr
, 0},
3569 {"macu.ww", 2, 0x48, mul_reg_opr_opr
, 0},
3570 {"macu.wp", 2, 0x48, mul_reg_opr_opr
, 0},
3571 {"macu.wl", 2, 0x48, mul_reg_opr_opr
, 0},
3573 {"macu.pb", 2, 0x48, mul_reg_opr_opr
, 0},
3574 {"macu.pw", 2, 0x48, mul_reg_opr_opr
, 0},
3575 {"macu.pp", 2, 0x48, mul_reg_opr_opr
, 0},
3576 {"macu.pl", 2, 0x48, mul_reg_opr_opr
, 0},
3578 {"macu.lb", 2, 0x48, mul_reg_opr_opr
, 0},
3579 {"macu.lw", 2, 0x48, mul_reg_opr_opr
, 0},
3580 {"macu.lp", 2, 0x48, mul_reg_opr_opr
, 0},
3581 {"macu.ll", 2, 0x48, mul_reg_opr_opr
, 0},
3586 {"mods", 2, 0x38, mul_reg_reg_reg
, 0},
3587 {"modu", 2, 0x38, mul_reg_reg_reg
, 0},
3589 {"mods.b", 2, 0x38, mul_reg_reg_opr
, 0},
3590 {"mods.w", 2, 0x38, mul_reg_reg_opr
, 0},
3591 {"mods.l", 2, 0x38, mul_reg_reg_opr
, 0},
3593 {"modu.b", 2, 0x38, mul_reg_reg_opr
, 0},
3594 {"modu.w", 2, 0x38, mul_reg_reg_opr
, 0},
3595 {"modu.l", 2, 0x38, mul_reg_reg_opr
, 0},
3597 {"mods.b", 2, 0x38, mul_reg_reg_imm
, 0},
3598 {"mods.w", 2, 0x38, mul_reg_reg_imm
, 0},
3599 {"mods.l", 2, 0x38, mul_reg_reg_imm
, 0},
3601 {"modu.b", 2, 0x38, mul_reg_reg_imm
, 0},
3602 {"modu.w", 2, 0x38, mul_reg_reg_imm
, 0},
3603 {"modu.l", 2, 0x38, mul_reg_reg_imm
, 0},
3605 {"mods.bb", 2, 0x38, mul_reg_opr_opr
, 0},
3606 {"mods.bw", 2, 0x38, mul_reg_opr_opr
, 0},
3607 {"mods.bp", 2, 0x38, mul_reg_opr_opr
, 0},
3608 {"mods.bl", 2, 0x38, mul_reg_opr_opr
, 0},
3610 {"mods.wb", 2, 0x38, mul_reg_opr_opr
, 0},
3611 {"mods.ww", 2, 0x38, mul_reg_opr_opr
, 0},
3612 {"mods.wp", 2, 0x38, mul_reg_opr_opr
, 0},
3613 {"mods.wl", 2, 0x38, mul_reg_opr_opr
, 0},
3615 {"mods.pb", 2, 0x38, mul_reg_opr_opr
, 0},
3616 {"mods.pw", 2, 0x38, mul_reg_opr_opr
, 0},
3617 {"mods.pp", 2, 0x38, mul_reg_opr_opr
, 0},
3618 {"mods.pl", 2, 0x38, mul_reg_opr_opr
, 0},
3620 {"mods.lb", 2, 0x38, mul_reg_opr_opr
, 0},
3621 {"mods.lw", 2, 0x38, mul_reg_opr_opr
, 0},
3622 {"mods.lp", 2, 0x38, mul_reg_opr_opr
, 0},
3623 {"mods.ll", 2, 0x38, mul_reg_opr_opr
, 0},
3625 {"modu.bb", 2, 0x38, mul_reg_opr_opr
, 0},
3626 {"modu.bw", 2, 0x38, mul_reg_opr_opr
, 0},
3627 {"modu.bp", 2, 0x38, mul_reg_opr_opr
, 0},
3628 {"modu.bl", 2, 0x38, mul_reg_opr_opr
, 0},
3630 {"modu.wb", 2, 0x38, mul_reg_opr_opr
, 0},
3631 {"modu.ww", 2, 0x38, mul_reg_opr_opr
, 0},
3632 {"modu.wp", 2, 0x38, mul_reg_opr_opr
, 0},
3633 {"modu.wl", 2, 0x38, mul_reg_opr_opr
, 0},
3635 {"modu.pb", 2, 0x38, mul_reg_opr_opr
, 0},
3636 {"modu.pw", 2, 0x38, mul_reg_opr_opr
, 0},
3637 {"modu.pp", 2, 0x38, mul_reg_opr_opr
, 0},
3638 {"modu.pl", 2, 0x38, mul_reg_opr_opr
, 0},
3640 {"modu.lb", 2, 0x38, mul_reg_opr_opr
, 0},
3641 {"modu.lw", 2, 0x38, mul_reg_opr_opr
, 0},
3642 {"modu.lp", 2, 0x38, mul_reg_opr_opr
, 0},
3643 {"modu.ll", 2, 0x38, mul_reg_opr_opr
, 0}
3647 /* Gas line assembler entry point. */
3649 /* This is the main entry point for the machine-dependent assembler. str
3650 points to a machine-dependent instruction. This function is supposed to
3651 emit the frags/bytes it assembles to. */
3653 md_assemble (char *str
)
3660 fail_line_pointer
= NULL
;
3662 /* Find the opcode end and get the opcode in 'name'. The opcode is forced
3663 lower case (the opcode table only has lower case op-codes). */
3664 for (op_start
= op_end
= str
;
3665 *op_end
&& !is_end_of_line
[(int)*op_end
] && *op_end
!= ' ';
3668 name
[nlen
] = TOLOWER (op_start
[nlen
]);
3670 gas_assert (nlen
< sizeof (name
) - 1);
3676 as_bad (_("No instruction or missing opcode."));
3680 input_line_pointer
= skip_whites (op_end
);
3683 for (i
= 0; i
< sizeof (opcodes
) / sizeof (opcodes
[0]); ++i
)
3685 const struct instruction
*opc
= opcodes
+ i
;
3686 if (0 == strcmp (name
, opc
->name
))
3688 if (opc
->parse_operands (opc
))
3694 as_bad (_("Invalid instruction: \"%s\""), str
);
3695 as_bad (_("First invalid token: \"%s\""), fail_line_pointer
);
3696 while (*input_line_pointer
++)
3704 /* Relocation, relaxation and frag conversions. */
3706 /* PC-relative offsets are relative to the start of the
3707 next instruction. That is, the address of the offset, plus its
3708 size, since the offset is always the last part of the insn. */
3710 md_pcrel_from (fixS
*fixP
)
3712 long ret
= fixP
->fx_size
+ fixP
->fx_frag
->fr_address
;
3713 if (fixP
->fx_addsy
&& S_IS_DEFINED (fixP
->fx_addsy
))
3714 ret
+= fixP
->fx_where
;
3720 /* We need a port-specific relaxation function to cope with sym2 - sym1
3721 relative expressions with both symbols in the same segment (but not
3722 necessarily in the same frag as this insn), for example:
3723 ldab sym2-(sym1-2),pc
3725 The offset can be 5, 9 or 16 bits long. */
3728 s12z_relax_frag (segT seg ATTRIBUTE_UNUSED
, fragS
*fragP ATTRIBUTE_UNUSED
,
3729 long stretch ATTRIBUTE_UNUSED
)
3735 md_convert_frag (bfd
*abfd ATTRIBUTE_UNUSED
, asection
*sec ATTRIBUTE_UNUSED
,
3736 fragS
*fragP ATTRIBUTE_UNUSED
)
3740 /* On an ELF system, we can't relax a weak symbol. The weak symbol
3741 can be overridden at final link time by a non weak symbol. We can
3742 relax externally visible symbol because there is no shared library
3743 and such symbol can't be overridden (unless they are weak). */
3745 /* Force truly undefined symbols to their maximum size, and generally set up
3746 the frag list to be relaxed. */
3748 md_estimate_size_before_relax (fragS
*fragP ATTRIBUTE_UNUSED
, asection
*segment ATTRIBUTE_UNUSED
)
3754 /* If while processing a fixup, a reloc really needs to be created
3755 then it is done here. */
3757 tc_gen_reloc (asection
*section
, fixS
*fixp
)
3759 arelent
*reloc
= XNEW (arelent
);
3760 reloc
->sym_ptr_ptr
= XNEW (asymbol
*);
3761 *reloc
->sym_ptr_ptr
= symbol_get_bfdsym (fixp
->fx_addsy
);
3762 reloc
->address
= fixp
->fx_frag
->fr_address
+ fixp
->fx_where
;
3763 reloc
->howto
= bfd_reloc_type_lookup (stdoutput
, fixp
->fx_r_type
);
3764 if (reloc
->howto
== (reloc_howto_type
*) NULL
)
3766 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
3767 _("Relocation %d is not supported by object file format."),
3768 (int) fixp
->fx_r_type
);
3772 if (0 == (section
->flags
& SEC_CODE
))
3773 reloc
->addend
= fixp
->fx_offset
;
3775 reloc
->addend
= fixp
->fx_addnumber
;
3780 /* See whether we need to force a relocation into the output file. */
3782 tc_s12z_force_relocation (fixS
*fixP
)
3784 return generic_force_reloc (fixP
);
3787 /* Here we decide which fixups can be adjusted to make them relative
3788 to the beginning of the section instead of the symbol. Basically
3789 we need to make sure that the linker relaxation is done
3790 correctly, so in some cases we force the original symbol to be
3793 tc_s12z_fix_adjustable (fixS
*fixP ATTRIBUTE_UNUSED
)
3799 md_apply_fix (fixS
*fixP
, valueT
*valP
, segT seg ATTRIBUTE_UNUSED
)
3803 if (fixP
->fx_addsy
== (symbolS
*) NULL
)
3806 /* We don't actually support subtracting a symbol. */
3807 if (fixP
->fx_subsy
!= (symbolS
*) NULL
)
3808 as_bad_where (fixP
->fx_file
, fixP
->fx_line
, _("Expression too complex."));
3811 Patch the instruction with the resolved operand. Elf relocation
3812 info will also be generated to take care of linker/loader fixups.
3814 char *where
= fixP
->fx_frag
->fr_literal
+ fixP
->fx_where
;
3816 switch (fixP
->fx_r_type
)
3819 ((bfd_byte
*) where
)[0] = (bfd_byte
) value
;
3822 bfd_putb16 ((bfd_vma
) value
, (unsigned char *) where
);
3825 case BFD_RELOC_S12Z_OPR
:
3826 bfd_putb24 ((bfd_vma
) value
, (unsigned char *) where
);
3829 bfd_putb32 ((bfd_vma
) value
, (unsigned char *) where
);
3831 case BFD_RELOC_16_PCREL
:
3832 if (value
< -0x8000 || value
> 0x7FFF)
3833 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
3834 _("Value out of 16-bit range."));
3836 bfd_putb16 ((bfd_vma
) value
| 0x8000, (unsigned char *) where
);
3840 as_fatal (_("Line %d: unknown relocation type: 0x%x."),
3841 fixP
->fx_line
, fixP
->fx_r_type
);
3845 /* Set the ELF specific flags. */
3847 s12z_elf_final_processing (void)