1 /* tc-s12z.c -- Assembler code for the Freescale S12Z
2 Copyright (C) 2018 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 "opcodes/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 int len
= p
- input_line_pointer
;
317 for (i
= 0; i
< S12Z_N_REGISTERS
; ++i
)
319 gas_assert (registers
[i
].name
);
321 if (0 == strncasecmp (registers
[i
].name
, input_line_pointer
, len
))
323 if ((0x1U
<< i
) & which
)
325 input_line_pointer
= p
;
336 lex_force_match (char x
)
338 char *p
= input_line_pointer
;
341 as_bad (_("Expecting '%c'"), x
);
345 input_line_pointer
++;
350 lex_opr (uint8_t *buffer
, int *n_bytes
, expressionS
*exp
)
352 char *ilp
= input_line_pointer
;
353 uint8_t *xb
= buffer
;
356 exp
->X_op
= O_absent
;
359 if (lex_imm_e4 (&imm
))
369 else if (lex_reg_name (REG_BIT_Dn
, ®
))
376 else if (lex_match ('['))
378 if (lex_expression (exp
))
380 long c
= exp
->X_add_number
;
383 if (lex_reg_name (REG_BIT_XYSP
, ®
))
386 if (c
<= 255 && c
>= -256)
396 *xb
|= (reg
- REG_X
) << 4;
400 for (i
= 1; i
< *n_bytes
; ++i
)
402 buffer
[i
] = c
>> (8 * (*n_bytes
- i
- 1));
407 as_bad (_("Bad operand for constant offset"));
420 else if (lex_reg_name (REG_BIT_Dn
, ®
))
422 if (!lex_force_match (','))
426 if (lex_reg_name (REG_BIT_XY
, ®2
))
430 *xb
|= (reg2
- REG_X
) << 4;
435 as_bad (_("Invalid operand for register offset"));
443 if (!lex_force_match (']'))
447 else if (lex_match ('('))
450 if (lex_constant (&c
))
452 if (!lex_force_match (','))
455 if (lex_reg_name (REG_BIT_XYSP
, ®2
))
457 if (reg2
!= REG_P
&& c
>= 0 && c
<= 15)
461 *xb
|= (reg2
- REG_X
) << 4;
464 else if (c
>= -256 && c
<= 255)
468 *xb
|= (reg2
- REG_X
) << 4;
477 *xb
|= (reg2
- REG_X
) << 4;
483 else if (lex_reg_name (REG_BIT_Dn
, ®2
))
485 if (c
>= -1 * (long) (0x1u
<< 17)
487 c
< (long) (0x1u
<< 17) - 1)
492 *xb
|= ((c
>> 16) & 0x03) << 4;
508 as_bad (_("Bad operand for constant offset"));
512 else if (lex_reg_name (REG_BIT_Dn
, ®
))
517 if (lex_reg_name (REG_BIT_XYS
, ®2
))
521 *xb
|= (reg2
- REG_X
) << 4;
526 as_bad (_("Invalid operand for register offset"));
535 else if (lex_reg_name (REG_BIT_XYS
, ®
))
541 as_bad (_("Invalid register for postdecrement operation"));
547 else if (reg
== REG_Y
)
550 else if (lex_match ('+'))
555 else if (reg
== REG_Y
)
557 else if (reg
== REG_S
)
565 else if (lex_match ('+'))
567 if (lex_reg_name (REG_BIT_XY
, ®
))
572 else if (reg
== REG_Y
)
577 as_bad (_("Invalid register for preincrement operation"));
581 else if (lex_match ('-'))
583 if (lex_reg_name (REG_BIT_XYS
, ®
))
588 else if (reg
== REG_Y
)
590 else if (reg
== REG_S
)
595 as_bad (_("Invalid register for predecrement operation"));
604 if (! lex_match (')'))
608 else if (lex_expression (exp
))
615 if (exp
->X_op
== O_constant
)
617 if (exp
->X_add_number
< (0x1U
<< 14))
621 *xb
|= exp
->X_add_number
>> 8;
622 buffer
[1] = exp
->X_add_number
;
624 else if (exp
->X_add_number
< (0x1U
<< 19))
627 if (exp
->X_add_number
& (0x1U
<< 17))
629 if (exp
->X_add_number
& (0x1U
<< 16))
632 buffer
[1] = exp
->X_add_number
>> 8;
633 buffer
[2] = exp
->X_add_number
;
639 buffer
[1] = exp
->X_add_number
>> 16;
640 buffer
[2] = exp
->X_add_number
>> 8;
641 buffer
[3] = exp
->X_add_number
;
648 fail_line_pointer
= input_line_pointer
;
649 input_line_pointer
= ilp
;
654 lex_offset (long *val
)
657 char *p
= input_line_pointer
;
662 if (*p
!= '+' && *p
!= '-')
665 bool negative
= (*p
== '-');
669 *val
= strtol (p
, &end
, 0);
674 input_line_pointer
= end
;
685 typedef int (*parse_operand_func
) (const struct instruction
*);
691 /* The "page" to which the instruction belongs.
692 This is also only a hint. Some instructions might have modes in both
696 /* This is a hint - and only a hint - about the opcode of the instruction.
697 The parse_operand_func is free to ignore it.
701 parse_operand_func parse_operands
;
703 /* Some instructions can be encoded with a different opcode */
708 no_operands (const struct instruction
*insn
)
710 if (*input_line_pointer
!= '\0')
712 as_bad (_("Garbage at end of instruction"));
716 char *f
= s12z_new_insn (insn
->page
);
718 number_to_chars_bigendian (f
++, PAGE2_PREBYTE
, 1);
720 number_to_chars_bigendian (f
++, insn
->opc
, 1);
725 /* Emit the code for an OPR address mode operand */
727 emit_opr (char *f
, const uint8_t *buffer
, int n_bytes
, expressionS
*exp
)
730 number_to_chars_bigendian (f
++, buffer
[0], 1);
731 if (exp
->X_op
!= O_absent
&& exp
->X_op
!= O_constant
)
733 fix_new_exp (frag_now
,
734 f
- frag_now
->fr_literal
,
740 for (i
= 1; i
< n_bytes
; ++i
)
741 number_to_chars_bigendian (f
++, buffer
[i
], 1);
746 /* Emit the code for a 24 bit direct address operand */
748 emit_ext24 (char *f
, long v
)
750 number_to_chars_bigendian (f
, v
, 3);
756 opr (const struct instruction
*insn
)
761 if (lex_opr (buffer
, &n_bytes
, &exp
))
763 /* Large constant direct values are more efficiently encoded as ext24 mode.
764 Otherwise a decision has to be deferred to a relax. */
765 if (exp
.X_op
== O_constant
767 && insn
->alt_opc
!= 0)
769 char *f
= s12z_new_insn (4);
771 /* I don't think there are any instances of page 2 opcodes in this case */
772 gas_assert (insn
->page
== 1);
774 number_to_chars_bigendian (f
++, insn
->alt_opc
, 1);
776 emit_ext24 (f
, exp
.X_add_number
);
780 char *f
= s12z_new_insn (n_bytes
+ 1);
781 number_to_chars_bigendian (f
++, insn
->opc
, 1);
783 emit_opr (f
, buffer
, n_bytes
, &exp
);
791 /* Parse a 15 bit offset, as an expression.
792 LONG_DISPLACEMENT will be set to true if the offset is wider than 7 bits.
795 lex_15_bit_offset (bool *long_displacement
, expressionS
*exp
)
797 char *ilp
= input_line_pointer
;
800 if (lex_offset (&val
))
802 exp
->X_op
= O_absent
;
803 exp
->X_add_number
= val
;
805 else if (lex_expression (exp
))
807 if (exp
->X_op
== O_constant
)
809 val
= exp
->X_add_number
;
813 /* If a symbol was parsed we don't know the displacement.
814 We have to assume it is long, and relax it later if possible. */
815 *long_displacement
= true;
821 exp
->X_op
= O_absent
;
825 if (val
> 0x3FFF || val
< -0x4000)
827 as_fatal (_("Offset is outside of 15 bit range"));
831 *long_displacement
= (val
> 63 || val
< -64);
836 fail_line_pointer
= input_line_pointer
;
837 input_line_pointer
= ilp
;
842 emit_15_bit_offset (char *f
, int where
, expressionS
*exp
)
845 if (exp
->X_op
!= O_absent
&& exp
->X_op
!= O_constant
)
847 exp
->X_add_number
+= where
;
848 fixS
*fix
= fix_new_exp (frag_now
,
849 f
- frag_now
->fr_literal
,
854 fix
->fx_addnumber
= where
- 2;
858 long val
= exp
->X_add_number
;
859 bool long_displacement
= (val
> 63 || val
< -64);
860 if (long_displacement
)
865 number_to_chars_bigendian (f
++, val
, long_displacement
? 2 : 1);
870 rel (const struct instruction
*insn
)
872 bool long_displacement
;
875 if (! lex_15_bit_offset (&long_displacement
, &exp
))
878 char *f
= s12z_new_insn (long_displacement
? 3 : 2);
879 number_to_chars_bigendian (f
++, insn
->opc
, 1);
880 emit_15_bit_offset (f
, 3, &exp
);
885 reg_inh (const struct instruction
*insn
)
888 if (lex_reg_name (REG_BIT_Dn
, ®
))
890 char *f
= s12z_new_insn (insn
->page
);
892 number_to_chars_bigendian (f
++, PAGE2_PREBYTE
, 1);
894 number_to_chars_bigendian (f
++, insn
->opc
+ reg
, 1);
902 /* Special case for CLR X and CLR Y */
904 clr_xy (const struct instruction
*insn ATTRIBUTE_UNUSED
)
907 if (lex_reg_name (REG_BIT_XY
, ®
))
909 char *f
= s12z_new_insn (1);
910 number_to_chars_bigendian (f
, 0x9a + reg
- REG_X
, 1);
917 /* Some instructions have a suffix like ".l", ".b", ".w" etc
918 which indicates the size of the operands. */
920 size_from_suffix (const struct instruction
*insn
, int idx
)
922 const char *dot
= strchr (insn
->name
, '.');
928 switch (dot
[1 + idx
])
943 as_fatal (_("Bad size"));
950 mul_reg_reg_reg (const struct instruction
*insn
)
952 char *ilp
= input_line_pointer
;
955 if (!lex_reg_name (REG_BIT_Dn
, &Dd
))
958 if (!lex_match (','))
962 if (!lex_reg_name (REG_BIT_Dn
, &Dj
))
965 if (!lex_match (','))
969 if (!lex_reg_name (REG_BIT_Dn
, &Dk
))
972 char *f
= s12z_new_insn (insn
->page
+ 1);
974 number_to_chars_bigendian (f
++, PAGE2_PREBYTE
, 1);
976 number_to_chars_bigendian (f
++, insn
->opc
+ Dd
, 1);
977 const char *dot
= strchrnul (insn
->name
, '.');
988 as_fatal (_("BAD MUL"));
995 number_to_chars_bigendian (f
++, mb
, 1);
1000 fail_line_pointer
= input_line_pointer
;
1001 input_line_pointer
= ilp
;
1007 mul_reg_reg_imm (const struct instruction
*insn
)
1009 char *ilp
= input_line_pointer
;
1012 if (!lex_reg_name (REG_BIT_Dn
, &Dd
))
1015 if (!lex_match (','))
1019 if (!lex_reg_name (REG_BIT_Dn
, &Dj
))
1022 if (!lex_match (','))
1026 if (!lex_imm (&imm
))
1030 int size
= size_from_suffix (insn
, 0);
1032 char *f
= s12z_new_insn (insn
->page
+ 1 + size
);
1033 if (insn
->page
== 2)
1034 number_to_chars_bigendian (f
++, PAGE2_PREBYTE
, 1);
1036 number_to_chars_bigendian (f
++, insn
->opc
+ Dd
, 1);
1038 const char *dot
= strchrnul (insn
->name
, '.');
1048 as_fatal (_("BAD MUL"));
1055 number_to_chars_bigendian (f
++, mb
, 1);
1056 number_to_chars_bigendian (f
++, imm
, size
);
1061 fail_line_pointer
= input_line_pointer
;
1062 input_line_pointer
= ilp
;
1068 mul_reg_reg_opr (const struct instruction
*insn
)
1070 char *ilp
= input_line_pointer
;
1073 if (!lex_reg_name (REG_BIT_Dn
, &Dd
))
1076 if (!lex_match (','))
1080 if (!lex_reg_name (REG_BIT_Dn
, &Dj
))
1083 if (!lex_match (','))
1089 if (!lex_opr (buffer
, &n_bytes
, &exp
))
1092 int size
= size_from_suffix (insn
, 0);
1094 char *f
= s12z_new_insn (insn
->page
+ 1 + n_bytes
);
1095 if (insn
->page
== 2)
1096 number_to_chars_bigendian (f
++, PAGE2_PREBYTE
, 1);
1098 number_to_chars_bigendian (f
++, insn
->opc
+ Dd
, 1);
1100 const char *dot
= strchrnul (insn
->name
, '.');
1110 as_fatal (_("BAD MUL"));
1117 number_to_chars_bigendian (f
++, mb
, 1);
1119 emit_opr (f
, buffer
, n_bytes
, &exp
);
1124 fail_line_pointer
= input_line_pointer
;
1125 input_line_pointer
= ilp
;
1130 mul_reg_opr_opr (const struct instruction
*insn
)
1132 char *ilp
= input_line_pointer
;
1135 if (!lex_reg_name (REG_BIT_Dn
, &Dd
))
1138 if (!lex_match (','))
1144 if (!lex_opr (buffer1
, &n_bytes1
, &exp1
))
1147 if (!lex_match (','))
1153 if (!lex_opr (buffer2
, &n_bytes2
, &exp2
))
1156 int size1
= size_from_suffix (insn
, 0);
1157 int size2
= size_from_suffix (insn
, 1);
1159 char *f
= s12z_new_insn (insn
->page
+ 1 + n_bytes1
+ n_bytes2
);
1160 if (insn
->page
== 2)
1161 number_to_chars_bigendian (f
++, PAGE2_PREBYTE
, 1);
1163 number_to_chars_bigendian (f
++, insn
->opc
+ Dd
, 1);
1165 const char *dot
= strchrnul (insn
->name
, '.');
1175 as_fatal (_("BAD MUL"));
1179 mb
|= (size1
- 1) << 4;
1180 mb
|= (size2
- 1) << 2;
1181 number_to_chars_bigendian (f
++, mb
, 1);
1183 f
= emit_opr (f
, buffer1
, n_bytes1
, &exp1
);
1184 f
= emit_opr (f
, buffer2
, n_bytes2
, &exp2
);
1189 fail_line_pointer
= input_line_pointer
;
1190 input_line_pointer
= ilp
;
1195 #define REG_BIT_GRP0 \
1196 ((0x1U << REG_D2) | \
1197 (0x1U << REG_D3) | \
1198 (0x1U << REG_CCH) | \
1199 (0x1U << REG_CCL) | \
1200 (0x1U << REG_D0) | \
1203 #define REG_BIT_GRP1 \
1204 ((0x1U << REG_D4) | \
1205 (0x1U << REG_D5) | \
1206 (0x1U << REG_D6) | \
1207 (0x1U << REG_D7) | \
1211 static const uint8_t reg_map
[] =
1231 lex_reg_list (uint16_t grp
, uint16_t *reg_bits
)
1233 if (lex_match (','))
1236 if (!lex_reg_name (grp
, ®
))
1238 *reg_bits
|= 0x1u
<< reg
;
1239 lex_reg_list (grp
, reg_bits
);
1247 psh_pull (const struct instruction
*insn
)
1250 (0 == strcmp ("pul", insn
->name
)) ? 0x80: 0x00;
1252 if (lex_match_string ("all16b"))
1256 else if (lex_match_string ("all"))
1263 if (!lex_reg_name (REG_BIT_GRP1
| REG_BIT_GRP0
, ®1
))
1265 uint16_t admitted_group
= 0;
1267 if ((0x1U
<< reg1
) & REG_BIT_GRP1
)
1268 admitted_group
= REG_BIT_GRP1
;
1269 else if ((0x1U
<< reg1
) & REG_BIT_GRP0
)
1270 admitted_group
= REG_BIT_GRP0
;
1272 uint16_t reg_bits
= 0x1 << reg1
;
1273 if (!lex_reg_list (admitted_group
, ®_bits
))
1276 if (reg_bits
& REG_BIT_GRP1
)
1280 for (i
= 0; i
< 16; ++i
)
1282 if (reg_bits
& (0x1u
<< i
))
1287 char *f
= s12z_new_insn (2);
1288 number_to_chars_bigendian (f
++, insn
->opc
, 1);
1289 number_to_chars_bigendian (f
++, pb
, 1);
1293 fail_line_pointer
= input_line_pointer
;
1299 tfr (const struct instruction
*insn
)
1302 if (!lex_reg_name (~0, ®1
))
1305 if (!lex_match (','))
1309 if (!lex_reg_name (~0, ®2
))
1312 if ((0 == strcasecmp ("sex", insn
->name
))
1313 || (0 == strcasecmp ("zex", insn
->name
)))
1315 if (registers
[reg1
].bytes
>= registers
[reg2
].bytes
)
1317 as_bad (_("Source register for %s must be smaller that the destination register"),
1323 char *f
= s12z_new_insn (1 + insn
->page
);
1324 if (insn
->page
== 2)
1325 number_to_chars_bigendian (f
++, PAGE2_PREBYTE
, 1);
1327 number_to_chars_bigendian (f
++, insn
->opc
, 1);
1328 number_to_chars_bigendian (f
++, reg1
<< 4 | reg2
, 1);
1333 fail_line_pointer
= input_line_pointer
;
1338 imm8 (const struct instruction
*insn
)
1341 if (! lex_imm (&imm
))
1343 if (imm
> 127 || imm
< -128)
1345 as_bad (_("Immediate value %ld is out of range for instruction %s"),
1349 char *f
= s12z_new_insn (2);
1350 number_to_chars_bigendian (f
++, insn
->opc
, 1);
1351 number_to_chars_bigendian (f
++, imm
, 1);
1357 reg_imm (const struct instruction
*insn
, int allowed_reg
)
1359 char *ilp
= input_line_pointer
;
1361 if (lex_reg_name (allowed_reg
, ®
))
1363 if (!lex_force_match (','))
1366 if (! lex_imm (&imm
))
1369 short size
= registers
[reg
].bytes
;
1370 char *f
= s12z_new_insn (insn
->page
+ size
);
1371 if (insn
->page
== 2)
1372 number_to_chars_bigendian (f
++, PAGE2_PREBYTE
, 1);
1374 number_to_chars_bigendian (f
++, insn
->opc
+ reg
, 1);
1375 number_to_chars_bigendian (f
++, imm
, size
);
1380 fail_line_pointer
= input_line_pointer
;
1381 input_line_pointer
= ilp
;
1387 regd_imm (const struct instruction
*insn
)
1389 return reg_imm (insn
, REG_BIT_Dn
);
1393 regdxy_imm (const struct instruction
*insn
)
1395 return reg_imm (insn
, REG_BIT_Dn
| REG_BIT_XY
);
1400 regs_imm (const struct instruction
*insn
)
1402 return reg_imm (insn
, 0x1U
<< REG_S
);
1406 trap_imm (const struct instruction
*insn ATTRIBUTE_UNUSED
)
1409 if (! lex_imm (&imm
))
1412 if (imm
< 0x92 || imm
> 0xFF ||
1413 (imm
>= 0xA0 && imm
<= 0xA7) ||
1414 (imm
>= 0xB0 && imm
<= 0xB7))
1416 as_bad (_("trap value %ld is not valid"), imm
);
1421 char *f
= s12z_new_insn (2);
1422 number_to_chars_bigendian (f
++, PAGE2_PREBYTE
, 1);
1423 number_to_chars_bigendian (f
++, imm
& 0xFF, 1);
1430 fail_line_pointer
= input_line_pointer
;
1436 /* Special one byte instruction CMP X, Y */
1438 regx_regy (const struct instruction
*insn
)
1441 if (lex_reg_name (0x1U
<< REG_X
, ®
))
1443 if (lex_force_match (','))
1445 if (lex_reg_name (0x1U
<< REG_Y
, ®
))
1447 char *f
= s12z_new_insn (1);
1448 number_to_chars_bigendian (f
, insn
->opc
, 1);
1456 /* Special one byte instruction SUB D6, X, Y */
1458 regd6_regx_regy (const struct instruction
*insn
)
1460 char *ilp
= input_line_pointer
;
1462 if (!lex_reg_name (0x1U
<< REG_D6
, ®
))
1465 if (!lex_match (','))
1468 if (!lex_reg_name (0x1U
<< REG_X
, ®
))
1471 if (!lex_match (','))
1474 if (!lex_reg_name (0x1U
<< REG_Y
, ®
))
1477 char *f
= s12z_new_insn (1);
1478 number_to_chars_bigendian (f
, insn
->opc
, 1);
1482 fail_line_pointer
= input_line_pointer
;
1483 input_line_pointer
= ilp
;
1487 /* Special one byte instruction SUB D6, Y, X */
1489 regd6_regy_regx (const struct instruction
*insn
)
1491 char *ilp
= input_line_pointer
;
1493 if (!lex_reg_name (0x1U
<< REG_D6
, ®
))
1496 if (!lex_match (','))
1499 if (!lex_reg_name (0x1U
<< REG_Y
, ®
))
1502 if (!lex_match (','))
1505 if (!lex_reg_name (0x1U
<< REG_X
, ®
))
1508 char *f
= s12z_new_insn (1);
1509 number_to_chars_bigendian (f
, insn
->opc
, 1);
1513 fail_line_pointer
= input_line_pointer
;
1514 input_line_pointer
= ilp
;
1519 reg_opr (const struct instruction
*insn
, int allowed_regs
)
1521 char *ilp
= input_line_pointer
;
1523 if (lex_reg_name (allowed_regs
, ®
))
1525 if (!lex_force_match (','))
1531 if (lex_opr (buffer
, &n_bytes
, &exp
))
1533 /* Large constant direct values are more efficiently encoded as ext24 mode.
1534 Otherwise a decision has to be deferred to a relax. */
1535 if (exp
.X_op
== O_constant
1536 && buffer
[0] == 0xFA
1537 && insn
->alt_opc
!= 0)
1539 char *f
= s12z_new_insn (4);
1541 /* I don't think there are any instances of page 2 opcodes in this case */
1542 gas_assert (insn
->page
== 1);
1544 number_to_chars_bigendian (f
++, insn
->alt_opc
+ reg
, 1);
1546 emit_ext24 (f
, exp
.X_add_number
);
1550 char *f
= s12z_new_insn (n_bytes
+ insn
->page
);
1552 if (insn
->page
== 2)
1553 number_to_chars_bigendian (f
++, PAGE2_PREBYTE
, 1);
1555 number_to_chars_bigendian (f
++, insn
->opc
+ reg
, 1);
1557 emit_opr (f
, buffer
, n_bytes
, &exp
);
1565 fail_line_pointer
= input_line_pointer
;
1566 input_line_pointer
= ilp
;
1572 regdxy_opr (const struct instruction
*insn
)
1574 return reg_opr (insn
, REG_BIT_Dn
| REG_BIT_XY
);
1578 regd_opr (const struct instruction
*insn
)
1580 return reg_opr (insn
, REG_BIT_Dn
);
1585 regs_opr (const struct instruction
*insn
)
1587 return reg_opr (insn
, 0x1U
<< REG_S
);
1591 imm_opr (const struct instruction
*insn
)
1593 char *ilp
= input_line_pointer
;
1595 if (!lex_imm (&imm
))
1598 if (!lex_match (','))
1604 if (!lex_opr (buffer
, &n_bytes
, &exp
))
1607 int size
= size_from_suffix (insn
, 0);
1608 char *f
= s12z_new_insn (1 + n_bytes
+ size
);
1609 number_to_chars_bigendian (f
++, insn
->opc
, 1);
1612 for (i
= 0; i
< size
; ++i
)
1613 number_to_chars_bigendian (f
++, imm
>> (CHAR_BIT
* (size
- i
- 1)), 1);
1615 emit_opr (f
, buffer
, n_bytes
, &exp
);
1620 fail_line_pointer
= input_line_pointer
;
1621 input_line_pointer
= ilp
;
1626 opr_opr (const struct instruction
*insn
)
1628 char *ilp
= input_line_pointer
;
1633 if (!lex_opr (buffer1
, &n_bytes1
, &exp1
))
1637 if (!lex_match (','))
1643 if (!lex_opr (buffer2
, &n_bytes2
, &exp2
))
1646 char *f
= s12z_new_insn (1 + n_bytes1
+ n_bytes2
);
1647 number_to_chars_bigendian (f
++, insn
->opc
, 1);
1649 f
= emit_opr (f
, buffer1
, n_bytes1
, &exp1
);
1650 f
= emit_opr (f
, buffer2
, n_bytes2
, &exp2
);
1655 fail_line_pointer
= input_line_pointer
;
1656 input_line_pointer
= ilp
;
1661 reg67sxy_opr (const struct instruction
*insn
)
1664 if (!lex_reg_name (REG_BIT_XYS
| (0x1U
<< REG_D6
) | (0x1U
<< REG_D7
), ®
))
1667 if (!lex_match (','))
1673 if (!lex_opr (buffer
, &n_bytes
, &exp
))
1676 char *f
= s12z_new_insn (1 + n_bytes
);
1677 number_to_chars_bigendian (f
++, insn
->opc
+ reg
- REG_D6
, 1);
1678 emit_opr (f
, buffer
, n_bytes
, &exp
);
1684 rotate (const struct instruction
*insn
, short dir
)
1689 if (lex_opr (buffer
, &n_bytes
, &exp
))
1691 char *f
= s12z_new_insn (n_bytes
+ 2);
1692 number_to_chars_bigendian (f
++, insn
->opc
, 1);
1693 int size
= size_from_suffix (insn
, 0);
1700 number_to_chars_bigendian (f
++, sb
, 1);
1701 emit_opr (f
, buffer
, n_bytes
, &exp
);
1710 rol (const struct instruction
*insn
)
1712 return rotate (insn
, 1);
1716 ror (const struct instruction
*insn
)
1718 return rotate (insn
, 0);
1722 /* Shift instruction with a register operand and an immediate #1 or #2
1723 left = 1; right = 0;
1724 logical = 0; arithmetic = 1;
1727 lex_shift_reg_imm1 (const struct instruction
*insn
, short type
, short dir
)
1730 This function is highly unusual and a bit wierd!
1731 It first matches the input against a register {d0, d1, ... d7} followed by an immediate
1733 Then, it rewinds the input and parses it again as a OPR.
1735 char *ilp
= input_line_pointer
;
1738 if (!lex_reg_name (REG_BIT_Dn
, &Dd
))
1743 if (!lex_match (','))
1747 if (!lex_imm (&imm
))
1750 if (imm
!= 1 && imm
!= 2)
1752 input_line_pointer
= ilp
;
1754 /* Now parse the first operand again */
1760 if (!lex_opr (buffer
, &n_bytes
, &exp
))
1763 gas_assert (n_bytes
== 1);
1771 char *f
= s12z_new_insn (3);
1772 number_to_chars_bigendian (f
++, insn
->opc
, 1);
1773 number_to_chars_bigendian (f
++, sb
, 1);
1774 emit_opr (f
, buffer
, n_bytes
, &exp
);
1779 fail_line_pointer
= input_line_pointer
;
1780 input_line_pointer
= ilp
;
1784 /* Shift instruction with a register operand.
1785 left = 1; right = 0;
1786 logical = 0; arithmetic = 1; */
1788 lex_shift_reg (const struct instruction
*insn
, short type
, short dir
)
1791 if (!lex_reg_name (REG_BIT_Dn
, &Dd
))
1796 if (!lex_match (','))
1799 if (!lex_reg_name (REG_BIT_Dn
, &Ds
))
1804 if (!lex_match (','))
1812 if (lex_reg_name (REG_BIT_Dn
, &Dn
))
1814 char *f
= s12z_new_insn (3);
1815 number_to_chars_bigendian (f
++, insn
->opc
| Dd
, 1);
1816 number_to_chars_bigendian (f
++, sb
, 1);
1819 number_to_chars_bigendian (f
++, xb
, 1);
1823 else if (lex_imm (&imm
))
1825 if (imm
< 0 || imm
> 31)
1827 as_bad (_("Shift value should be in the range [0,31]"));
1832 if (imm
== 1 || imm
== 2)
1839 sb
|= (imm
& 0x01) << 3;
1842 char *f
= s12z_new_insn (n_bytes
);
1843 number_to_chars_bigendian (f
++, insn
->opc
| Dd
, 1);
1844 number_to_chars_bigendian (f
++, sb
, 1);
1849 number_to_chars_bigendian (f
++, xb
, 1);
1856 fail_line_pointer
= input_line_pointer
;
1861 impute_shift_dir_and_type (const struct instruction
*insn
, short *type
, short *dir
)
1865 switch (insn
->name
[0])
1874 as_fatal (_("Bad shift mode"));
1878 switch (insn
->name
[2])
1887 as_fatal (_("Bad shift *direction"));
1892 /* Shift instruction with a OPR operand */
1894 shift_two_operand (const struct instruction
*insn
)
1897 char *ilp
= input_line_pointer
;
1901 impute_shift_dir_and_type (insn
, &type
, &dir
);
1905 int size
= size_from_suffix (insn
, 0);
1911 if (!lex_opr (buffer
, &n_opr_bytes
, &exp
))
1914 if (!lex_match (','))
1918 if (!lex_imm (&imm
))
1921 if (imm
!= 1 && imm
!= 2)
1927 char *f
= s12z_new_insn (2 + n_opr_bytes
);
1928 number_to_chars_bigendian (f
++, insn
->opc
, 1);
1929 number_to_chars_bigendian (f
++, sb
, 1);
1930 emit_opr (f
, buffer
, n_opr_bytes
, &exp
);
1935 fail_line_pointer
= input_line_pointer
;
1936 input_line_pointer
= ilp
;
1940 /* Shift instruction with a OPR operand */
1942 shift_opr_imm (const struct instruction
*insn
)
1944 char *ilp
= input_line_pointer
;
1948 impute_shift_dir_and_type (insn
, &type
, &dir
);
1951 if (!lex_reg_name (REG_BIT_Dn
, &Dd
))
1954 if (!lex_match (','))
1963 if (!lex_opr (buffer1
, &n_opr_bytes1
, &exp1
))
1966 n_bytes
+= n_opr_bytes1
;
1967 if (!lex_match (','))
1971 int n_opr_bytes2
= 0;
1974 bool immediate
= false;
1979 else if (!lex_opr (buffer2
, &n_opr_bytes2
, &exp2
))
1984 int size
= size_from_suffix (insn
, 0);
1994 if (imm
== 2 || imm
== 1)
2009 n_bytes
+= n_opr_bytes2
;
2013 char *f
= s12z_new_insn (n_bytes
);
2014 number_to_chars_bigendian (f
++, insn
->opc
| Dd
, 1);
2015 number_to_chars_bigendian (f
++, sb
, 1);
2016 f
= emit_opr (f
, buffer1
, n_opr_bytes1
, &exp1
);
2019 if (imm
!= 1 && imm
!= 2)
2021 number_to_chars_bigendian (f
++, 0x70 | (imm
>> 1), 1);
2026 f
= emit_opr (f
, buffer2
, n_opr_bytes2
, &exp2
);
2032 fail_line_pointer
= input_line_pointer
;
2033 input_line_pointer
= ilp
;
2037 /* Shift instruction with a register operand */
2039 shift_reg (const struct instruction
*insn
)
2043 impute_shift_dir_and_type (insn
, &type
, &dir
);
2045 if (lex_shift_reg_imm1 (insn
, type
, dir
))
2048 return lex_shift_reg (insn
, type
, dir
);
2052 bm_regd_imm (const struct instruction
*insn
)
2054 char *ilp
= input_line_pointer
;
2056 if (!lex_reg_name (REG_BIT_Dn
, &Di
))
2059 if (!lex_match (','))
2063 if (!lex_imm (&imm
))
2067 uint8_t bm
= imm
<< 3;
2070 char *f
= s12z_new_insn (2);
2071 number_to_chars_bigendian (f
++, insn
->opc
, 1);
2072 number_to_chars_bigendian (f
++, bm
, 1);
2077 fail_line_pointer
= input_line_pointer
;
2078 input_line_pointer
= ilp
;
2083 bm_opr_reg (const struct instruction
*insn
)
2085 char *ilp
= input_line_pointer
;
2091 if (!lex_opr (buffer
, &n_opr_bytes
, &exp
))
2094 if (!lex_match (','))
2098 if (!lex_reg_name (REG_BIT_Dn
, &Dn
))
2101 uint8_t bm
= Dn
<< 4;
2102 int size
= size_from_suffix (insn
, 0);
2103 bm
|= (size
- 1) << 2;
2106 char *f
= s12z_new_insn (2 + n_opr_bytes
);
2107 number_to_chars_bigendian (f
++, insn
->opc
, 1);
2108 number_to_chars_bigendian (f
++, bm
, 1);
2110 emit_opr (f
, buffer
, n_opr_bytes
, &exp
);
2115 fail_line_pointer
= input_line_pointer
;
2116 input_line_pointer
= ilp
;
2122 bm_opr_imm (const struct instruction
*insn
)
2124 char *ilp
= input_line_pointer
;
2130 if (!lex_opr (buffer
, &n_opr_bytes
, &exp
))
2133 if (!lex_match (','))
2138 if (!lex_imm (&imm
))
2141 int size
= size_from_suffix (insn
, 0);
2143 if (imm
< 0 || imm
>= size
* 8)
2145 as_bad (_("Immediate operand %ld is inappropriate for size of instruction"), imm
);
2154 bm
|= (imm
& 0x07) << 4;
2158 char *f
= s12z_new_insn (2 + n_opr_bytes
);
2159 number_to_chars_bigendian (f
++, insn
->opc
, 1);
2160 number_to_chars_bigendian (f
++, bm
, 1);
2161 emit_opr (f
, buffer
, n_opr_bytes
, &exp
);
2166 fail_line_pointer
= input_line_pointer
;
2167 input_line_pointer
= ilp
;
2173 bm_regd_reg (const struct instruction
*insn
)
2175 char *ilp
= input_line_pointer
;
2177 if (!lex_reg_name (REG_BIT_Dn
, &Di
))
2180 if (!lex_match (','))
2184 if (!lex_reg_name (REG_BIT_Dn
, &Dn
))
2187 uint8_t bm
= Dn
<< 4;
2190 uint8_t xb
= Di
| 0xb8;
2192 char *f
= s12z_new_insn (3);
2193 number_to_chars_bigendian (f
++, insn
->opc
, 1);
2194 number_to_chars_bigendian (f
++, bm
, 1);
2195 number_to_chars_bigendian (f
++, xb
, 1);
2200 fail_line_pointer
= input_line_pointer
;
2201 input_line_pointer
= ilp
;
2210 bf_reg_opr_imm (const struct instruction
*insn
, short ie
)
2212 char *ilp
= input_line_pointer
;
2214 if (!lex_reg_name (REG_BIT_Dn
, &Dd
))
2217 if (!lex_match (','))
2224 if (!lex_opr (buffer
, &n_bytes
, &exp
))
2227 if (!lex_match (','))
2231 if (!lex_imm (&width
))
2234 if (width
< 0 || width
> 31)
2236 as_bad (_("Invalid width value for %s"), insn
->name
);
2240 if (!lex_match (':'))
2244 if (!lex_constant (&offset
))
2247 if (offset
< 0 || offset
> 31)
2249 as_bad (_("Invalid offset value for %s"), insn
->name
);
2253 uint8_t i1
= width
<< 5;
2256 int size
= size_from_suffix (insn
, 0);
2257 uint8_t bb
= ie
? 0x80 : 0x00;
2259 bb
|= (size
- 1) << 2;
2262 char *f
= s12z_new_insn (4 + n_bytes
);
2263 number_to_chars_bigendian (f
++, PAGE2_PREBYTE
, 1);
2264 number_to_chars_bigendian (f
++, 0x08 | Dd
, 1);
2265 number_to_chars_bigendian (f
++, bb
, 1);
2266 number_to_chars_bigendian (f
++, i1
, 1);
2268 emit_opr (f
, buffer
, n_bytes
, &exp
);
2273 fail_line_pointer
= input_line_pointer
;
2274 input_line_pointer
= ilp
;
2280 bf_opr_reg_imm (const struct instruction
*insn
, short ie
)
2282 char *ilp
= input_line_pointer
;
2286 if (!lex_opr (buffer
, &n_bytes
, &exp
))
2289 if (!lex_match (','))
2293 if (!lex_reg_name (REG_BIT_Dn
, &Ds
))
2296 if (!lex_match (','))
2300 if (!lex_imm (&width
))
2303 if (width
< 0 || width
> 31)
2305 as_bad (_("Invalid width value for %s"), insn
->name
);
2309 if (!lex_match (':'))
2313 if (!lex_constant (&offset
))
2316 if (offset
< 0 || offset
> 31)
2318 as_bad (_("Invalid offset value for %s"), insn
->name
);
2322 uint8_t i1
= width
<< 5;
2325 int size
= size_from_suffix (insn
, 0);
2326 uint8_t bb
= ie
? 0x80 : 0x00;
2328 bb
|= (size
- 1) << 2;
2331 char *f
= s12z_new_insn (4 + n_bytes
);
2332 number_to_chars_bigendian (f
++, PAGE2_PREBYTE
, 1);
2333 number_to_chars_bigendian (f
++, 0x08 | Ds
, 1);
2334 number_to_chars_bigendian (f
++, bb
, 1);
2335 number_to_chars_bigendian (f
++, i1
, 1);
2337 emit_opr (f
, buffer
, n_bytes
, &exp
);
2342 fail_line_pointer
= input_line_pointer
;
2343 input_line_pointer
= ilp
;
2350 bf_reg_reg_imm (const struct instruction
*insn
, short ie
)
2352 char *ilp
= input_line_pointer
;
2354 if (!lex_reg_name (REG_BIT_Dn
, &Dd
))
2357 if (!lex_match (','))
2361 if (!lex_reg_name (REG_BIT_Dn
, &Ds
))
2364 if (!lex_match (','))
2368 if (!lex_imm (&width
))
2371 if (width
< 0 || width
> 31)
2373 as_bad (_("Invalid width value for %s"), insn
->name
);
2377 if (!lex_match (':'))
2381 if (!lex_constant (&offset
))
2384 if (offset
< 0 || offset
> 31)
2386 as_bad (_("Invalid offset value for %s"), insn
->name
);
2390 uint8_t bb
= ie
? 0x80 : 0x00;
2395 uint8_t i1
= width
<< 5;
2398 char *f
= s12z_new_insn (4);
2399 number_to_chars_bigendian (f
++, PAGE2_PREBYTE
, 1);
2400 number_to_chars_bigendian (f
++, 0x08 | Dd
, 1);
2401 number_to_chars_bigendian (f
++, bb
, 1);
2402 number_to_chars_bigendian (f
++, i1
, 1);
2407 fail_line_pointer
= input_line_pointer
;
2408 input_line_pointer
= ilp
;
2413 bf_reg_reg_reg (const struct instruction
*insn ATTRIBUTE_UNUSED
, short ie
)
2415 char *ilp
= input_line_pointer
;
2417 if (!lex_reg_name (REG_BIT_Dn
, &Dd
))
2420 if (!lex_match (','))
2424 if (!lex_reg_name (REG_BIT_Dn
, &Ds
))
2427 if (!lex_match (','))
2431 if (!lex_reg_name ((0x01u
<< REG_D2
) |
2438 uint8_t bb
= ie
? 0x80 : 0x00;
2442 char *f
= s12z_new_insn (3);
2443 number_to_chars_bigendian (f
++, PAGE2_PREBYTE
, 1);
2444 number_to_chars_bigendian (f
++, 0x08 | Dd
, 1);
2445 number_to_chars_bigendian (f
++, bb
, 1);
2450 fail_line_pointer
= input_line_pointer
;
2451 input_line_pointer
= ilp
;
2456 bf_opr_reg_reg (const struct instruction
*insn
, short ie
)
2458 char *ilp
= input_line_pointer
;
2463 if (!lex_opr (buffer
, &n_bytes
, &exp
))
2466 if (!lex_match (','))
2471 if (!lex_reg_name (REG_BIT_Dn
, &Ds
))
2474 if (!lex_match (','))
2479 if (!lex_reg_name ((0x01u
<< REG_D2
) |
2486 int size
= size_from_suffix (insn
, 0);
2487 uint8_t bb
= ie
? 0x80 : 0x00;
2490 bb
|= (size
- 1) << 2;
2492 char *f
= s12z_new_insn (3 + n_bytes
);
2493 number_to_chars_bigendian (f
++, PAGE2_PREBYTE
, 1);
2494 number_to_chars_bigendian (f
++, 0x08 | Ds
, 1);
2495 number_to_chars_bigendian (f
++, bb
, 1);
2497 emit_opr (f
, buffer
, n_bytes
, &exp
);
2502 fail_line_pointer
= input_line_pointer
;
2503 input_line_pointer
= ilp
;
2509 bf_reg_opr_reg (const struct instruction
*insn
, short ie
)
2511 char *ilp
= input_line_pointer
;
2513 if (!lex_reg_name (REG_BIT_Dn
, &Dd
))
2516 if (!lex_match (','))
2523 if (!lex_opr (buffer
, &n_bytes
, &exp
))
2526 if (!lex_match (','))
2530 if (!lex_reg_name ((0x01u
<< REG_D2
) |
2537 int size
= size_from_suffix (insn
, 0);
2538 uint8_t bb
= ie
? 0x80 : 0x00;
2541 bb
|= (size
- 1) << 2;
2543 char *f
= s12z_new_insn (3 + n_bytes
);
2544 number_to_chars_bigendian (f
++, PAGE2_PREBYTE
, 1);
2545 number_to_chars_bigendian (f
++, 0x08 | Dd
, 1);
2546 number_to_chars_bigendian (f
++, bb
, 1);
2548 emit_opr (f
, buffer
, n_bytes
, &exp
);
2553 fail_line_pointer
= input_line_pointer
;
2554 input_line_pointer
= ilp
;
2561 bfe_reg_reg_reg (const struct instruction
*insn
)
2563 return bf_reg_reg_reg (insn
, 0);
2567 bfi_reg_reg_reg (const struct instruction
*insn
)
2569 return bf_reg_reg_reg (insn
, 1);
2573 bfe_reg_reg_imm (const struct instruction
*insn
)
2575 return bf_reg_reg_imm (insn
, 0);
2579 bfi_reg_reg_imm (const struct instruction
*insn
)
2581 return bf_reg_reg_imm (insn
, 1);
2586 bfe_reg_opr_reg (const struct instruction
*insn
)
2588 return bf_reg_opr_reg (insn
, 0);
2592 bfi_reg_opr_reg (const struct instruction
*insn
)
2594 return bf_reg_opr_reg (insn
, 1);
2599 bfe_opr_reg_reg (const struct instruction
*insn
)
2601 return bf_opr_reg_reg (insn
, 0);
2605 bfi_opr_reg_reg (const struct instruction
*insn
)
2607 return bf_opr_reg_reg (insn
, 1);
2611 bfe_reg_opr_imm (const struct instruction
*insn
)
2613 return bf_reg_opr_imm (insn
, 0);
2617 bfi_reg_opr_imm (const struct instruction
*insn
)
2619 return bf_reg_opr_imm (insn
, 1);
2623 bfe_opr_reg_imm (const struct instruction
*insn
)
2625 return bf_opr_reg_imm (insn
, 0);
2629 bfi_opr_reg_imm (const struct instruction
*insn
)
2631 return bf_opr_reg_imm (insn
, 1);
2638 tb_reg_rel (const struct instruction
*insn
)
2640 char *ilp
= input_line_pointer
;
2643 if (!lex_reg_name (REG_BIT_Dn
| REG_BIT_XY
, ®
))
2646 if (!lex_match (','))
2649 bool long_displacement
;
2651 if (! lex_15_bit_offset (&long_displacement
, &exp
))
2655 if (reg
== REG_X
|| reg
== REG_Y
)
2666 if (0 == strncmp (insn
->name
+ 2, "ne", 2))
2668 else if (0 == strncmp (insn
->name
+ 2, "eq", 2))
2670 else if (0 == strncmp (insn
->name
+ 2, "pl", 2))
2672 else if (0 == strncmp (insn
->name
+ 2, "mi", 2))
2674 else if (0 == strncmp (insn
->name
+ 2, "gt", 2))
2676 else if (0 == strncmp (insn
->name
+ 2, "le", 2))
2679 switch (insn
->name
[0])
2691 char *f
= s12z_new_insn (long_displacement
? 4 : 3);
2692 number_to_chars_bigendian (f
++, insn
->opc
, 1);
2693 number_to_chars_bigendian (f
++, lb
, 1);
2695 emit_15_bit_offset (f
, 4, &exp
);
2700 fail_line_pointer
= input_line_pointer
;
2701 input_line_pointer
= ilp
;
2707 tb_opr_rel (const struct instruction
*insn
)
2709 char *ilp
= input_line_pointer
;
2714 if (!lex_opr (buffer
, &n_bytes
, &exp
))
2717 if (!lex_match (','))
2720 bool long_displacement
;
2722 if (! lex_15_bit_offset (&long_displacement
, &exp2
))
2727 if (0 == strncmp (insn
->name
+ 2, "ne", 2))
2729 else if (0 == strncmp (insn
->name
+ 2, "eq", 2))
2731 else if (0 == strncmp (insn
->name
+ 2, "pl", 2))
2733 else if (0 == strncmp (insn
->name
+ 2, "mi", 2))
2735 else if (0 == strncmp (insn
->name
+ 2, "gt", 2))
2737 else if (0 == strncmp (insn
->name
+ 2, "le", 2))
2740 switch (insn
->name
[0])
2752 int size
= size_from_suffix (insn
, 0);
2756 char *f
= s12z_new_insn (n_bytes
+ (long_displacement
? 4 : 3));
2757 number_to_chars_bigendian (f
++, insn
->opc
, 1);
2758 number_to_chars_bigendian (f
++, lb
, 1);
2759 f
= emit_opr (f
, buffer
, n_bytes
, &exp
);
2761 emit_15_bit_offset (f
, n_bytes
+ 4, &exp2
);
2766 fail_line_pointer
= input_line_pointer
;
2767 input_line_pointer
= ilp
;
2775 test_br_reg_reg_rel (const struct instruction
*insn
)
2777 char *ilp
= input_line_pointer
;
2780 if (!lex_reg_name (REG_BIT_Dn
, &Di
))
2783 if (!lex_match (','))
2788 if (!lex_reg_name (REG_BIT_Dn
, &Dn
))
2791 if (!lex_match (','))
2795 bool long_displacement
;
2797 if (! lex_15_bit_offset (&long_displacement
, &exp
))
2806 char *f
= s12z_new_insn (long_displacement
? 5 : 4);
2807 number_to_chars_bigendian (f
++, insn
->opc
, 1);
2808 number_to_chars_bigendian (f
++, bm
, 1);
2809 number_to_chars_bigendian (f
++, xb
, 1);
2811 emit_15_bit_offset (f
, 5, &exp
);
2816 fail_line_pointer
= input_line_pointer
;
2817 input_line_pointer
= ilp
;
2822 test_br_opr_reg_rel (const struct instruction
*insn
)
2824 char *ilp
= input_line_pointer
;
2829 if (!lex_opr (buffer
, &n_bytes
, &exp
))
2832 if (!lex_match (','))
2836 if (!lex_reg_name (REG_BIT_Dn
, &Dn
))
2839 if (!lex_match (','))
2844 int size
= size_from_suffix (insn
, 0);
2845 bm
|= (size
-1) << 2;
2847 bool long_displacement
;
2850 if (! lex_15_bit_offset (&long_displacement
, &exp2
))
2853 int n
= n_bytes
+ (long_displacement
? 4 : 3);
2854 char *f
= s12z_new_insn (n
);
2855 number_to_chars_bigendian (f
++, insn
->opc
, 1);
2856 number_to_chars_bigendian (f
++, bm
, 1);
2857 f
= emit_opr (f
, buffer
, n_bytes
, &exp
);
2859 emit_15_bit_offset (f
, n
, &exp2
);
2864 fail_line_pointer
= input_line_pointer
;
2865 input_line_pointer
= ilp
;
2871 test_br_opr_imm_rel (const struct instruction
*insn
)
2873 char *ilp
= input_line_pointer
;
2878 if (!lex_opr (buffer
, &n_bytes
, &exp
))
2881 if (!lex_match (','))
2885 if (!lex_imm (&imm
))
2888 if (imm
< 0 || imm
> 31)
2891 if (!lex_match (','))
2894 bool long_displacement
;
2896 if (! lex_15_bit_offset (&long_displacement
, &exp2
))
2899 int size
= size_from_suffix (insn
, 0);
2902 bm
|= (imm
& 0x07) << 4;
2903 bm
|= (imm
>> 3) & 0x03;
2909 char *f
= s12z_new_insn (n_bytes
+ (long_displacement
? 4 : 3));
2910 number_to_chars_bigendian (f
++, insn
->opc
, 1);
2911 number_to_chars_bigendian (f
++, bm
, 1);
2912 f
= emit_opr (f
, buffer
, n_bytes
, &exp
);
2914 emit_15_bit_offset (f
, n_bytes
+ 4, &exp2
);
2919 fail_line_pointer
= input_line_pointer
;
2920 input_line_pointer
= ilp
;
2926 test_br_reg_imm_rel (const struct instruction
*insn
)
2928 char *ilp
= input_line_pointer
;
2931 if (!lex_reg_name (REG_BIT_Dn
, &Di
))
2934 if (!lex_match (','))
2938 if (!lex_imm (&imm
))
2941 if (imm
< 0 || imm
> 31)
2945 if (!lex_match (','))
2948 bool long_displacement
;
2950 if (! lex_15_bit_offset (&long_displacement
, &exp
))
2956 char *f
= s12z_new_insn (long_displacement
? 4 : 3);
2957 number_to_chars_bigendian (f
++, insn
->opc
, 1);
2958 number_to_chars_bigendian (f
++, bm
, 1);
2960 emit_15_bit_offset (f
, 4, &exp
);
2965 fail_line_pointer
= input_line_pointer
;
2966 input_line_pointer
= ilp
;
2973 static const struct instruction opcodes
[] = {
2974 {"bgnd", 1, 0x00, no_operands
, 0},
2975 {"nop", 1, 0x01, no_operands
, 0},
2977 {"brclr", 1, 0x02, test_br_reg_reg_rel
, 0},
2978 {"brset", 1, 0x03, test_br_reg_reg_rel
, 0},
2980 {"brclr", 1, 0x02, test_br_reg_imm_rel
, 0},
2981 {"brset", 1, 0x03, test_br_reg_imm_rel
, 0},
2983 {"brclr.b", 1, 0x02, test_br_opr_reg_rel
, 0},
2984 {"brclr.w", 1, 0x02, test_br_opr_reg_rel
, 0},
2985 {"brclr.l", 1, 0x02, test_br_opr_reg_rel
, 0},
2987 {"brset.b", 1, 0x03, test_br_opr_reg_rel
, 0},
2988 {"brset.w", 1, 0x03, test_br_opr_reg_rel
, 0},
2989 {"brset.l", 1, 0x03, test_br_opr_reg_rel
, 0},
2991 {"brclr.b", 1, 0x02, test_br_opr_imm_rel
, 0},
2992 {"brclr.w", 1, 0x02, test_br_opr_imm_rel
, 0},
2993 {"brclr.l", 1, 0x02, test_br_opr_imm_rel
, 0},
2995 {"brset.b", 1, 0x03, test_br_opr_imm_rel
, 0},
2996 {"brset.w", 1, 0x03, test_br_opr_imm_rel
, 0},
2997 {"brset.l", 1, 0x03, test_br_opr_imm_rel
, 0},
2999 {"psh", 1, 0x04, psh_pull
, 0},
3000 {"pul", 1, 0x04, psh_pull
, 0},
3002 {"rts", 1, 0x05, no_operands
, 0},
3003 {"lea", 1, 0x06, reg67sxy_opr
, 0},
3005 {"dbne", 1, 0x0b, tb_reg_rel
, 0},
3006 {"dbeq", 1, 0x0b, tb_reg_rel
, 0},
3007 {"dbpl", 1, 0x0b, tb_reg_rel
, 0},
3008 {"dbmi", 1, 0x0b, tb_reg_rel
, 0},
3009 {"dbgt", 1, 0x0b, tb_reg_rel
, 0},
3010 {"dble", 1, 0x0b, tb_reg_rel
, 0},
3012 {"dbne.b", 1, 0x0b, tb_opr_rel
, 0},
3013 {"dbeq.b", 1, 0x0b, tb_opr_rel
, 0},
3014 {"dbpl.b", 1, 0x0b, tb_opr_rel
, 0},
3015 {"dbmi.b", 1, 0x0b, tb_opr_rel
, 0},
3016 {"dbgt.b", 1, 0x0b, tb_opr_rel
, 0},
3017 {"dble.b", 1, 0x0b, tb_opr_rel
, 0},
3019 {"dbne.w", 1, 0x0b, tb_opr_rel
, 0},
3020 {"dbeq.w", 1, 0x0b, tb_opr_rel
, 0},
3021 {"dbpl.w", 1, 0x0b, tb_opr_rel
, 0},
3022 {"dbmi.w", 1, 0x0b, tb_opr_rel
, 0},
3023 {"dbgt.w", 1, 0x0b, tb_opr_rel
, 0},
3024 {"dble.w", 1, 0x0b, tb_opr_rel
, 0},
3026 {"dbne.p", 1, 0x0b, tb_opr_rel
, 0},
3027 {"dbeq.p", 1, 0x0b, tb_opr_rel
, 0},
3028 {"dbpl.p", 1, 0x0b, tb_opr_rel
, 0},
3029 {"dbmi.p", 1, 0x0b, tb_opr_rel
, 0},
3030 {"dbgt.p", 1, 0x0b, tb_opr_rel
, 0},
3031 {"dble.p", 1, 0x0b, tb_opr_rel
, 0},
3033 {"dbne.l", 1, 0x0b, tb_opr_rel
, 0},
3034 {"dbeq.l", 1, 0x0b, tb_opr_rel
, 0},
3035 {"dbpl.l", 1, 0x0b, tb_opr_rel
, 0},
3036 {"dbmi.l", 1, 0x0b, tb_opr_rel
, 0},
3037 {"dbgt.l", 1, 0x0b, tb_opr_rel
, 0},
3038 {"dble.l", 1, 0x0b, tb_opr_rel
, 0},
3040 {"tbne", 1, 0x0b, tb_reg_rel
, 0},
3041 {"tbeq", 1, 0x0b, tb_reg_rel
, 0},
3042 {"tbpl", 1, 0x0b, tb_reg_rel
, 0},
3043 {"tbmi", 1, 0x0b, tb_reg_rel
, 0},
3044 {"tbgt", 1, 0x0b, tb_reg_rel
, 0},
3045 {"tble", 1, 0x0b, tb_reg_rel
, 0},
3047 {"tbne.b", 1, 0x0b, tb_opr_rel
, 0},
3048 {"tbeq.b", 1, 0x0b, tb_opr_rel
, 0},
3049 {"tbpl.b", 1, 0x0b, tb_opr_rel
, 0},
3050 {"tbmi.b", 1, 0x0b, tb_opr_rel
, 0},
3051 {"tbgt.b", 1, 0x0b, tb_opr_rel
, 0},
3052 {"tble.b", 1, 0x0b, tb_opr_rel
, 0},
3054 {"tbne.w", 1, 0x0b, tb_opr_rel
, 0},
3055 {"tbeq.w", 1, 0x0b, tb_opr_rel
, 0},
3056 {"tbpl.w", 1, 0x0b, tb_opr_rel
, 0},
3057 {"tbmi.w", 1, 0x0b, tb_opr_rel
, 0},
3058 {"tbgt.w", 1, 0x0b, tb_opr_rel
, 0},
3059 {"tble.w", 1, 0x0b, tb_opr_rel
, 0},
3061 {"tbne.p", 1, 0x0b, tb_opr_rel
, 0},
3062 {"tbeq.p", 1, 0x0b, tb_opr_rel
, 0},
3063 {"tbpl.p", 1, 0x0b, tb_opr_rel
, 0},
3064 {"tbmi.p", 1, 0x0b, tb_opr_rel
, 0},
3065 {"tbgt.p", 1, 0x0b, tb_opr_rel
, 0},
3066 {"tble.p", 1, 0x0b, tb_opr_rel
, 0},
3068 {"tbne.l", 1, 0x0b, tb_opr_rel
, 0},
3069 {"tbeq.l", 1, 0x0b, tb_opr_rel
, 0},
3070 {"tbpl.l", 1, 0x0b, tb_opr_rel
, 0},
3071 {"tbmi.l", 1, 0x0b, tb_opr_rel
, 0},
3072 {"tbgt.l", 1, 0x0b, tb_opr_rel
, 0},
3073 {"tble.l", 1, 0x0b, tb_opr_rel
, 0},
3075 {"mov.b", 1, 0x0c, imm_opr
, 0},
3076 {"mov.w", 1, 0x0d, imm_opr
, 0},
3077 {"mov.p", 1, 0x0e, imm_opr
, 0},
3078 {"mov.l", 1, 0x0f, imm_opr
, 0},
3080 {"rol", 1, 0x10, rol
, 0},
3081 {"rol.b", 1, 0x10, rol
, 0},
3082 {"rol.w", 1, 0x10, rol
, 0},
3083 {"rol.p", 1, 0x10, rol
, 0},
3084 {"rol.l", 1, 0x10, rol
, 0},
3086 {"ror", 1, 0x10, ror
, 0},
3087 {"ror.b", 1, 0x10, ror
, 0},
3088 {"ror.w", 1, 0x10, ror
, 0},
3089 {"ror.p", 1, 0x10, ror
, 0},
3090 {"ror.l", 1, 0x10, ror
, 0},
3092 {"lsl", 1, 0x10, shift_reg
, 0},
3093 {"lsr", 1, 0x10, shift_reg
, 0},
3094 {"asl", 1, 0x10, shift_reg
, 0},
3095 {"asr", 1, 0x10, shift_reg
, 0},
3097 {"lsl.b", 1, 0x10, shift_two_operand
, 0},
3098 {"lsl.w", 1, 0x10, shift_two_operand
, 0},
3099 {"lsl.p", 1, 0x10, shift_two_operand
, 0},
3100 {"lsl.l", 1, 0x10, shift_two_operand
, 0},
3101 {"asl.b", 1, 0x10, shift_two_operand
, 0},
3102 {"asl.w", 1, 0x10, shift_two_operand
, 0},
3103 {"asl.p", 1, 0x10, shift_two_operand
, 0},
3104 {"asl.l", 1, 0x10, shift_two_operand
, 0},
3106 {"lsr.b", 1, 0x10, shift_two_operand
, 0},
3107 {"lsr.w", 1, 0x10, shift_two_operand
, 0},
3108 {"lsr.p", 1, 0x10, shift_two_operand
, 0},
3109 {"lsr.l", 1, 0x10, shift_two_operand
, 0},
3110 {"asr.b", 1, 0x10, shift_two_operand
, 0},
3111 {"asr.w", 1, 0x10, shift_two_operand
, 0},
3112 {"asr.p", 1, 0x10, shift_two_operand
, 0},
3113 {"asr.l", 1, 0x10, shift_two_operand
, 0},
3115 {"lsl.b", 1, 0x10, shift_opr_imm
, 0},
3116 {"lsl.w", 1, 0x10, shift_opr_imm
, 0},
3117 {"lsl.p", 1, 0x10, shift_opr_imm
, 0},
3118 {"lsl.l", 1, 0x10, shift_opr_imm
, 0},
3119 {"asl.b", 1, 0x10, shift_opr_imm
, 0},
3120 {"asl.w", 1, 0x10, shift_opr_imm
, 0},
3121 {"asl.p", 1, 0x10, shift_opr_imm
, 0},
3122 {"asl.l", 1, 0x10, shift_opr_imm
, 0},
3124 {"lsr.b", 1, 0x10, shift_opr_imm
, 0},
3125 {"lsr.w", 1, 0x10, shift_opr_imm
, 0},
3126 {"lsr.p", 1, 0x10, shift_opr_imm
, 0},
3127 {"lsr.l", 1, 0x10, shift_opr_imm
, 0},
3128 {"asr.b", 1, 0x10, shift_opr_imm
, 0},
3129 {"asr.w", 1, 0x10, shift_opr_imm
, 0},
3130 {"asr.p", 1, 0x10, shift_opr_imm
, 0},
3131 {"asr.l", 1, 0x10, shift_opr_imm
, 0},
3133 {"mov.b", 1, 0x1c, opr_opr
, 0},
3134 {"mov.w", 1, 0x1d, opr_opr
, 0},
3135 {"mov.p", 1, 0x1e, opr_opr
, 0},
3136 {"mov.l", 1, 0x1f, opr_opr
, 0},
3138 {"bra", 1, 0x20, rel
, 0},
3139 {"bsr", 1, 0x21, rel
, 0},
3140 {"bhi", 1, 0x22, rel
, 0},
3141 {"bls", 1, 0x23, rel
, 0},
3142 {"bcc", 1, 0x24, rel
, 0},
3143 {"bcs", 1, 0x25, rel
, 0},
3144 {"bne", 1, 0x26, rel
, 0},
3145 {"beq", 1, 0x27, rel
, 0},
3146 {"bvc", 1, 0x28, rel
, 0},
3147 {"bvs", 1, 0x29, rel
, 0},
3148 {"bpl", 1, 0x2a, rel
, 0},
3149 {"bmi", 1, 0x2b, rel
, 0},
3150 {"bge", 1, 0x2c, rel
, 0},
3151 {"blt", 1, 0x2d, rel
, 0},
3152 {"bgt", 1, 0x2e, rel
, 0},
3153 {"ble", 1, 0x2f, rel
, 0},
3155 {"inc", 1, 0x30, reg_inh
, 0},
3156 {"clr", 1, 0x38, reg_inh
, 0},
3157 {"dec", 1, 0x40, reg_inh
, 0},
3159 {"muls", 1, 0x48, mul_reg_reg_reg
, 0},
3160 {"mulu", 1, 0x48, mul_reg_reg_reg
, 0},
3162 {"muls.b", 1, 0x48, mul_reg_reg_opr
, 0},
3163 {"muls.w", 1, 0x48, mul_reg_reg_opr
, 0},
3164 {"muls.l", 1, 0x48, mul_reg_reg_opr
, 0},
3166 {"mulu.b", 1, 0x48, mul_reg_reg_opr
, 0},
3167 {"mulu.w", 1, 0x48, mul_reg_reg_opr
, 0},
3168 {"mulu.l", 1, 0x48, mul_reg_reg_opr
, 0},
3170 {"muls.b", 1, 0x48, mul_reg_reg_imm
, 0},
3171 {"muls.w", 1, 0x48, mul_reg_reg_imm
, 0},
3172 {"muls.l", 1, 0x48, mul_reg_reg_imm
, 0},
3174 {"mulu.b", 1, 0x48, mul_reg_reg_imm
, 0},
3175 {"mulu.w", 1, 0x48, mul_reg_reg_imm
, 0},
3176 {"mulu.l", 1, 0x48, mul_reg_reg_imm
, 0},
3178 {"muls.bb", 1, 0x48, mul_reg_opr_opr
, 0},
3179 {"muls.bw", 1, 0x48, mul_reg_opr_opr
, 0},
3180 {"muls.bp", 1, 0x48, mul_reg_opr_opr
, 0},
3181 {"muls.bl", 1, 0x48, mul_reg_opr_opr
, 0},
3183 {"muls.wb", 1, 0x48, mul_reg_opr_opr
, 0},
3184 {"muls.ww", 1, 0x48, mul_reg_opr_opr
, 0},
3185 {"muls.wp", 1, 0x48, mul_reg_opr_opr
, 0},
3186 {"muls.wl", 1, 0x48, mul_reg_opr_opr
, 0},
3188 {"muls.pb", 1, 0x48, mul_reg_opr_opr
, 0},
3189 {"muls.pw", 1, 0x48, mul_reg_opr_opr
, 0},
3190 {"muls.pp", 1, 0x48, mul_reg_opr_opr
, 0},
3191 {"muls.pl", 1, 0x48, mul_reg_opr_opr
, 0},
3193 {"muls.lb", 1, 0x48, mul_reg_opr_opr
, 0},
3194 {"muls.lw", 1, 0x48, mul_reg_opr_opr
, 0},
3195 {"muls.lp", 1, 0x48, mul_reg_opr_opr
, 0},
3196 {"muls.ll", 1, 0x48, mul_reg_opr_opr
, 0},
3198 {"mulu.bb", 1, 0x48, mul_reg_opr_opr
, 0},
3199 {"mulu.bw", 1, 0x48, mul_reg_opr_opr
, 0},
3200 {"mulu.bp", 1, 0x48, mul_reg_opr_opr
, 0},
3201 {"mulu.bl", 1, 0x48, mul_reg_opr_opr
, 0},
3203 {"mulu.wb", 1, 0x48, mul_reg_opr_opr
, 0},
3204 {"mulu.ww", 1, 0x48, mul_reg_opr_opr
, 0},
3205 {"mulu.wp", 1, 0x48, mul_reg_opr_opr
, 0},
3206 {"mulu.wl", 1, 0x48, mul_reg_opr_opr
, 0},
3208 {"mulu.pb", 1, 0x48, mul_reg_opr_opr
, 0},
3209 {"mulu.pw", 1, 0x48, mul_reg_opr_opr
, 0},
3210 {"mulu.pp", 1, 0x48, mul_reg_opr_opr
, 0},
3211 {"mulu.pl", 1, 0x48, mul_reg_opr_opr
, 0},
3213 {"mulu.lb", 1, 0x48, mul_reg_opr_opr
, 0},
3214 {"mulu.lw", 1, 0x48, mul_reg_opr_opr
, 0},
3215 {"mulu.lp", 1, 0x48, mul_reg_opr_opr
, 0},
3216 {"mulu.ll", 1, 0x48, mul_reg_opr_opr
, 0},
3218 {"add", 1, 0x50, regd_imm
, 0},
3219 {"and", 1, 0x58, regd_imm
, 0},
3221 {"add", 1, 0x60, regd_opr
, 0},
3222 {"and", 1, 0x68, regd_opr
, 0},
3224 {"sub", 1, 0x70, regd_imm
, 0},
3225 {"or", 1, 0x78, regd_imm
, 0},
3227 {"sub", 1, 0x80, regd_opr
, 0},
3228 {"or", 1, 0x88, regd_opr
, 0},
3230 {"ld", 1, 0x90, regdxy_imm
, 0},
3232 {"clr", 1, 0x9a, clr_xy
, 0},
3233 {"tfr", 1, 0x9e, tfr
, 0},
3234 {"zex", 1, 0x9e, tfr
, 0},
3236 {"ld", 1, 0xa0, regdxy_opr
, 0xb0},
3238 {"jmp", 1, 0xaa, opr
, 0xba},
3239 {"jsr", 1, 0xab, opr
, 0xbb},
3241 {"exg", 1, 0xae, tfr
, 0},
3242 {"sex", 1, 0xae, tfr
, 0},
3244 {"st", 1, 0xc0, regdxy_opr
, 0xd0},
3246 {"andcc", 1, 0xce, imm8
, 0},
3247 {"orcc", 1, 0xde, imm8
, 0},
3249 {"inc.b", 1, 0x9c, opr
, 0},
3250 {"inc.w", 1, 0x9d, opr
, 0},
3251 {"inc.l", 1, 0x9f, opr
, 0},
3253 {"dec.b", 1, 0xac, opr
, 0},
3254 {"dec.w", 1, 0xad, opr
, 0},
3255 {"dec.l", 1, 0xaf, opr
, 0},
3257 {"clr.b", 1, 0xbc, opr
, 0},
3258 {"clr.w", 1, 0xbd, opr
, 0},
3259 {"clr.p", 1, 0xbe, opr
, 0},
3260 {"clr.l", 1, 0xbf, opr
, 0},
3262 {"com.b", 1, 0xcc, opr
, 0},
3263 {"com.w", 1, 0xcd, opr
, 0},
3264 {"com.l", 1, 0xcf, opr
, 0},
3266 {"neg.b", 1, 0xdc, opr
, 0},
3267 {"neg.w", 1, 0xdd, opr
, 0},
3268 {"neg.l", 1, 0xdf, opr
, 0},
3270 {"bclr", 1, 0xec, bm_regd_imm
, 0},
3271 {"bset", 1, 0xed, bm_regd_imm
, 0},
3272 {"btgl", 1, 0xee, bm_regd_imm
, 0},
3274 {"bclr", 1, 0xec, bm_regd_reg
, 0},
3275 {"bset", 1, 0xed, bm_regd_reg
, 0},
3276 {"btgl", 1, 0xee, bm_regd_reg
, 0},
3278 {"bclr.b", 1, 0xec, bm_opr_imm
, 0},
3279 {"bclr.w", 1, 0xec, bm_opr_imm
, 0},
3280 {"bclr.l", 1, 0xec, bm_opr_imm
, 0},
3282 {"bset.b", 1, 0xed, bm_opr_imm
, 0},
3283 {"bset.w", 1, 0xed, bm_opr_imm
, 0},
3284 {"bset.l", 1, 0xed, bm_opr_imm
, 0},
3286 {"btgl.b", 1, 0xee, bm_opr_imm
, 0},
3287 {"btgl.w", 1, 0xee, bm_opr_imm
, 0},
3288 {"btgl.l", 1, 0xee, bm_opr_imm
, 0},
3290 {"bclr.b", 1, 0xec, bm_opr_reg
, 0},
3291 {"bclr.w", 1, 0xec, bm_opr_reg
, 0},
3292 {"bclr.l", 1, 0xec, bm_opr_reg
, 0},
3294 {"bset.b", 1, 0xed, bm_opr_reg
, 0},
3295 {"bset.w", 1, 0xed, bm_opr_reg
, 0},
3296 {"bset.l", 1, 0xed, bm_opr_reg
, 0},
3298 {"btgl.b", 1, 0xee, bm_opr_reg
, 0},
3299 {"btgl.w", 1, 0xee, bm_opr_reg
, 0},
3300 {"btgl.l", 1, 0xee, bm_opr_reg
, 0},
3302 {"cmp", 1, 0xe0, regdxy_imm
, 0},
3303 {"cmp", 1, 0xf0, regdxy_opr
, 0},
3305 {"cmp", 1, 0xfc, regx_regy
, 0},
3306 {"sub", 1, 0xfd, regd6_regx_regy
, 0},
3307 {"sub", 1, 0xfe, regd6_regy_regx
, 0},
3309 {"swi", 1, 0xff, no_operands
, 0},
3313 /* The -10 below is a kludge. The opcode is in fact 0x00 */
3314 {"ld", 2, -10, regs_opr
, 0},
3316 /* The -9 below is a kludge. The opcode is in fact 0x01 */
3317 {"st", 2, -9, regs_opr
, 0},
3319 /* The -8 below is a kludge. The opcode is in fact 0x02 */
3320 {"cmp", 2, -8, regs_opr
, 0},
3322 /* The -7 below is a kludge. The opcode is in fact 0x03 */
3323 {"ld", 2, -7, regs_imm
, 0},
3325 /* The -6 below is a kludge. The opcode is in fact 0x04 */
3326 {"cmp", 2, -6, regs_imm
, 0},
3328 {"bfext", 2, 0x08, bfe_reg_reg_reg
, 0},
3329 {"bfext", 2, 0x08, bfe_reg_reg_imm
, 0},
3330 {"bfext.b", 2, 0x08, bfe_reg_opr_reg
, 0},
3331 {"bfext.w", 2, 0x08, bfe_reg_opr_reg
, 0},
3332 {"bfext.p", 2, 0x08, bfe_reg_opr_reg
, 0},
3333 {"bfext.l", 2, 0x08, bfe_reg_opr_reg
, 0},
3334 {"bfext.b", 2, 0x08, bfe_opr_reg_reg
, 0},
3335 {"bfext.w", 2, 0x08, bfe_opr_reg_reg
, 0},
3336 {"bfext.p", 2, 0x08, bfe_opr_reg_reg
, 0},
3337 {"bfext.l", 2, 0x08, bfe_opr_reg_reg
, 0},
3338 {"bfext.b", 2, 0x08, bfe_reg_opr_imm
, 0},
3339 {"bfext.w", 2, 0x08, bfe_reg_opr_imm
, 0},
3340 {"bfext.p", 2, 0x08, bfe_reg_opr_imm
, 0},
3341 {"bfext.l", 2, 0x08, bfe_reg_opr_imm
, 0},
3342 {"bfext.b", 2, 0x08, bfe_opr_reg_imm
, 0},
3343 {"bfext.w", 2, 0x08, bfe_opr_reg_imm
, 0},
3344 {"bfext.p", 2, 0x08, bfe_opr_reg_imm
, 0},
3345 {"bfext.l", 2, 0x08, bfe_opr_reg_imm
, 0},
3348 {"bfins", 2, 0x08, bfi_reg_reg_reg
, 0},
3349 {"bfins", 2, 0x08, bfi_reg_reg_imm
, 0},
3350 {"bfins.b", 2, 0x08, bfi_reg_opr_reg
, 0},
3351 {"bfins.w", 2, 0x08, bfi_reg_opr_reg
, 0},
3352 {"bfins.p", 2, 0x08, bfi_reg_opr_reg
, 0},
3353 {"bfins.l", 2, 0x08, bfi_reg_opr_reg
, 0},
3354 {"bfins.b", 2, 0x08, bfi_opr_reg_reg
, 0},
3355 {"bfins.w", 2, 0x08, bfi_opr_reg_reg
, 0},
3356 {"bfins.p", 2, 0x08, bfi_opr_reg_reg
, 0},
3357 {"bfins.l", 2, 0x08, bfi_opr_reg_reg
, 0},
3358 {"bfins.b", 2, 0x08, bfi_reg_opr_imm
, 0},
3359 {"bfins.w", 2, 0x08, bfi_reg_opr_imm
, 0},
3360 {"bfins.p", 2, 0x08, bfi_reg_opr_imm
, 0},
3361 {"bfins.l", 2, 0x08, bfi_reg_opr_imm
, 0},
3362 {"bfins.b", 2, 0x08, bfi_opr_reg_imm
, 0},
3363 {"bfins.w", 2, 0x08, bfi_opr_reg_imm
, 0},
3364 {"bfins.p", 2, 0x08, bfi_opr_reg_imm
, 0},
3365 {"bfins.l", 2, 0x08, bfi_opr_reg_imm
, 0},
3368 {"minu", 2, 0x10, regd_opr
, 0},
3369 {"maxu", 2, 0x18, regd_opr
, 0},
3370 {"mins", 2, 0x20, regd_opr
, 0},
3371 {"maxs", 2, 0x28, regd_opr
, 0},
3373 {"clb", 2, 0x91, tfr
, 0},
3375 {"trap", 2, 0x00, trap_imm
, 0},
3376 {"abs", 2, 0x40, reg_inh
, 0},
3377 {"sat", 2, 0xa0, reg_inh
, 0},
3379 {"rti", 2, 0x90, no_operands
, 0},
3380 {"stop", 2, 0x05, no_operands
, 0},
3381 {"wai", 2, 0x06, no_operands
, 0},
3382 {"sys", 2, 0x07, no_operands
, 0},
3384 {"bit", 2, 0x58, regd_imm
, 0},
3385 {"bit", 2, 0x68, regd_opr
, 0},
3387 {"adc", 2, 0x50, regd_imm
, 0},
3388 {"adc", 2, 0x60, regd_opr
, 0},
3390 {"sbc", 2, 0x70, regd_imm
, 0},
3391 {"eor", 2, 0x78, regd_imm
, 0},
3393 {"sbc", 2, 0x80, regd_opr
, 0},
3394 {"eor", 2, 0x88, regd_opr
, 0},
3396 {"divs", 2, 0x30, mul_reg_reg_reg
, 0},
3397 {"divu", 2, 0x30, mul_reg_reg_reg
, 0},
3399 {"divs.b", 2, 0x30, mul_reg_reg_opr
, 0},
3400 {"divs.w", 2, 0x30, mul_reg_reg_opr
, 0},
3401 {"divs.l", 2, 0x30, mul_reg_reg_opr
, 0},
3403 {"divu.b", 2, 0x30, mul_reg_reg_opr
, 0},
3404 {"divu.w", 2, 0x30, mul_reg_reg_opr
, 0},
3405 {"divu.l", 2, 0x30, mul_reg_reg_opr
, 0},
3407 {"divs.b", 2, 0x30, mul_reg_reg_imm
, 0},
3408 {"divs.w", 2, 0x30, mul_reg_reg_imm
, 0},
3409 {"divs.l", 2, 0x30, mul_reg_reg_imm
, 0},
3411 {"divu.b", 2, 0x30, mul_reg_reg_imm
, 0},
3412 {"divu.w", 2, 0x30, mul_reg_reg_imm
, 0},
3413 {"divu.l", 2, 0x30, mul_reg_reg_imm
, 0},
3415 {"divs.bb", 2, 0x30, mul_reg_opr_opr
, 0},
3416 {"divs.bw", 2, 0x30, mul_reg_opr_opr
, 0},
3417 {"divs.bp", 2, 0x30, mul_reg_opr_opr
, 0},
3418 {"divs.bl", 2, 0x30, mul_reg_opr_opr
, 0},
3420 {"divs.wb", 2, 0x30, mul_reg_opr_opr
, 0},
3421 {"divs.ww", 2, 0x30, mul_reg_opr_opr
, 0},
3422 {"divs.wp", 2, 0x30, mul_reg_opr_opr
, 0},
3423 {"divs.wl", 2, 0x30, mul_reg_opr_opr
, 0},
3425 {"divs.pb", 2, 0x30, mul_reg_opr_opr
, 0},
3426 {"divs.pw", 2, 0x30, mul_reg_opr_opr
, 0},
3427 {"divs.pp", 2, 0x30, mul_reg_opr_opr
, 0},
3428 {"divs.pl", 2, 0x30, mul_reg_opr_opr
, 0},
3430 {"divs.lb", 2, 0x30, mul_reg_opr_opr
, 0},
3431 {"divs.lw", 2, 0x30, mul_reg_opr_opr
, 0},
3432 {"divs.lp", 2, 0x30, mul_reg_opr_opr
, 0},
3433 {"divs.ll", 2, 0x30, mul_reg_opr_opr
, 0},
3435 {"divu.bb", 2, 0x30, mul_reg_opr_opr
, 0},
3436 {"divu.bw", 2, 0x30, mul_reg_opr_opr
, 0},
3437 {"divu.bp", 2, 0x30, mul_reg_opr_opr
, 0},
3438 {"divu.bl", 2, 0x30, mul_reg_opr_opr
, 0},
3440 {"divu.wb", 2, 0x30, mul_reg_opr_opr
, 0},
3441 {"divu.ww", 2, 0x30, mul_reg_opr_opr
, 0},
3442 {"divu.wp", 2, 0x30, mul_reg_opr_opr
, 0},
3443 {"divu.wl", 2, 0x30, mul_reg_opr_opr
, 0},
3445 {"divu.pb", 2, 0x30, mul_reg_opr_opr
, 0},
3446 {"divu.pw", 2, 0x30, mul_reg_opr_opr
, 0},
3447 {"divu.pp", 2, 0x30, mul_reg_opr_opr
, 0},
3448 {"divu.pl", 2, 0x30, mul_reg_opr_opr
, 0},
3450 {"divu.lb", 2, 0x30, mul_reg_opr_opr
, 0},
3451 {"divu.lw", 2, 0x30, mul_reg_opr_opr
, 0},
3452 {"divu.lp", 2, 0x30, mul_reg_opr_opr
, 0},
3453 {"divu.ll", 2, 0x30, mul_reg_opr_opr
, 0},
3457 {"qmuls", 2, 0xb0, mul_reg_reg_reg
, 0},
3458 {"qmulu", 2, 0xb0, mul_reg_reg_reg
, 0},
3460 {"qmuls.b", 2, 0xb0, mul_reg_reg_opr
, 0},
3461 {"qmuls.w", 2, 0xb0, mul_reg_reg_opr
, 0},
3462 {"qmuls.l", 2, 0xb0, mul_reg_reg_opr
, 0},
3464 {"qmulu.b", 2, 0xb0, mul_reg_reg_opr
, 0},
3465 {"qmulu.w", 2, 0xb0, mul_reg_reg_opr
, 0},
3466 {"qmulu.l", 2, 0xb0, mul_reg_reg_opr
, 0},
3468 {"qmuls.b", 2, 0xb0, mul_reg_reg_imm
, 0},
3469 {"qmuls.w", 2, 0xb0, mul_reg_reg_imm
, 0},
3470 {"qmuls.l", 2, 0xb0, mul_reg_reg_imm
, 0},
3472 {"qmulu.b", 2, 0xb0, mul_reg_reg_imm
, 0},
3473 {"qmulu.w", 2, 0xb0, mul_reg_reg_imm
, 0},
3474 {"qmulu.l", 2, 0xb0, mul_reg_reg_imm
, 0},
3476 {"qmuls.bb", 2, 0xb0, mul_reg_opr_opr
, 0},
3477 {"qmuls.bw", 2, 0xb0, mul_reg_opr_opr
, 0},
3478 {"qmuls.bp", 2, 0xb0, mul_reg_opr_opr
, 0},
3479 {"qmuls.bl", 2, 0xb0, mul_reg_opr_opr
, 0},
3481 {"qmuls.wb", 2, 0xb0, mul_reg_opr_opr
, 0},
3482 {"qmuls.ww", 2, 0xb0, mul_reg_opr_opr
, 0},
3483 {"qmuls.wp", 2, 0xb0, mul_reg_opr_opr
, 0},
3484 {"qmuls.wl", 2, 0xb0, mul_reg_opr_opr
, 0},
3486 {"qmuls.pb", 2, 0xb0, mul_reg_opr_opr
, 0},
3487 {"qmuls.pw", 2, 0xb0, mul_reg_opr_opr
, 0},
3488 {"qmuls.pp", 2, 0xb0, mul_reg_opr_opr
, 0},
3489 {"qmuls.pl", 2, 0xb0, mul_reg_opr_opr
, 0},
3491 {"qmuls.lb", 2, 0xb0, mul_reg_opr_opr
, 0},
3492 {"qmuls.lw", 2, 0xb0, mul_reg_opr_opr
, 0},
3493 {"qmuls.lp", 2, 0xb0, mul_reg_opr_opr
, 0},
3494 {"qmuls.ll", 2, 0xb0, mul_reg_opr_opr
, 0},
3496 {"qmulu.bb", 2, 0xb0, mul_reg_opr_opr
, 0},
3497 {"qmulu.bw", 2, 0xb0, mul_reg_opr_opr
, 0},
3498 {"qmulu.bp", 2, 0xb0, mul_reg_opr_opr
, 0},
3499 {"qmulu.bl", 2, 0xb0, mul_reg_opr_opr
, 0},
3501 {"qmulu.wb", 2, 0xb0, mul_reg_opr_opr
, 0},
3502 {"qmulu.ww", 2, 0xb0, mul_reg_opr_opr
, 0},
3503 {"qmulu.wp", 2, 0xb0, mul_reg_opr_opr
, 0},
3504 {"qmulu.wl", 2, 0xb0, mul_reg_opr_opr
, 0},
3506 {"qmulu.pb", 2, 0xb0, mul_reg_opr_opr
, 0},
3507 {"qmulu.pw", 2, 0xb0, mul_reg_opr_opr
, 0},
3508 {"qmulu.pp", 2, 0xb0, mul_reg_opr_opr
, 0},
3509 {"qmulu.pl", 2, 0xb0, mul_reg_opr_opr
, 0},
3511 {"qmulu.lb", 2, 0xb0, mul_reg_opr_opr
, 0},
3512 {"qmulu.lw", 2, 0xb0, mul_reg_opr_opr
, 0},
3513 {"qmulu.lp", 2, 0xb0, mul_reg_opr_opr
, 0},
3514 {"qmulu.ll", 2, 0xb0, mul_reg_opr_opr
, 0},
3519 {"macs", 2, 0x48, mul_reg_reg_reg
, 0},
3520 {"macu", 2, 0x48, mul_reg_reg_reg
, 0},
3522 {"macs.b", 2, 0x48, mul_reg_reg_opr
, 0},
3523 {"macs.w", 2, 0x48, mul_reg_reg_opr
, 0},
3524 {"macs.l", 2, 0x48, mul_reg_reg_opr
, 0},
3526 {"macu.b", 2, 0x48, mul_reg_reg_opr
, 0},
3527 {"macu.w", 2, 0x48, mul_reg_reg_opr
, 0},
3528 {"macu.l", 2, 0x48, mul_reg_reg_opr
, 0},
3530 {"macs.b", 2, 0x48, mul_reg_reg_imm
, 0},
3531 {"macs.w", 2, 0x48, mul_reg_reg_imm
, 0},
3532 {"macs.l", 2, 0x48, mul_reg_reg_imm
, 0},
3534 {"macu.b", 2, 0x48, mul_reg_reg_imm
, 0},
3535 {"macu.w", 2, 0x48, mul_reg_reg_imm
, 0},
3536 {"macu.l", 2, 0x48, mul_reg_reg_imm
, 0},
3538 {"macs.bb", 2, 0x48, mul_reg_opr_opr
, 0},
3539 {"macs.bw", 2, 0x48, mul_reg_opr_opr
, 0},
3540 {"macs.bp", 2, 0x48, mul_reg_opr_opr
, 0},
3541 {"macs.bl", 2, 0x48, mul_reg_opr_opr
, 0},
3543 {"macs.wb", 2, 0x48, mul_reg_opr_opr
, 0},
3544 {"macs.ww", 2, 0x48, mul_reg_opr_opr
, 0},
3545 {"macs.wp", 2, 0x48, mul_reg_opr_opr
, 0},
3546 {"macs.wl", 2, 0x48, mul_reg_opr_opr
, 0},
3548 {"macs.pb", 2, 0x48, mul_reg_opr_opr
, 0},
3549 {"macs.pw", 2, 0x48, mul_reg_opr_opr
, 0},
3550 {"macs.pp", 2, 0x48, mul_reg_opr_opr
, 0},
3551 {"macs.pl", 2, 0x48, mul_reg_opr_opr
, 0},
3553 {"macs.lb", 2, 0x48, mul_reg_opr_opr
, 0},
3554 {"macs.lw", 2, 0x48, mul_reg_opr_opr
, 0},
3555 {"macs.lp", 2, 0x48, mul_reg_opr_opr
, 0},
3556 {"macs.ll", 2, 0x48, mul_reg_opr_opr
, 0},
3558 {"macu.bb", 2, 0x48, mul_reg_opr_opr
, 0},
3559 {"macu.bw", 2, 0x48, mul_reg_opr_opr
, 0},
3560 {"macu.bp", 2, 0x48, mul_reg_opr_opr
, 0},
3561 {"macu.bl", 2, 0x48, mul_reg_opr_opr
, 0},
3563 {"macu.wb", 2, 0x48, mul_reg_opr_opr
, 0},
3564 {"macu.ww", 2, 0x48, mul_reg_opr_opr
, 0},
3565 {"macu.wp", 2, 0x48, mul_reg_opr_opr
, 0},
3566 {"macu.wl", 2, 0x48, mul_reg_opr_opr
, 0},
3568 {"macu.pb", 2, 0x48, mul_reg_opr_opr
, 0},
3569 {"macu.pw", 2, 0x48, mul_reg_opr_opr
, 0},
3570 {"macu.pp", 2, 0x48, mul_reg_opr_opr
, 0},
3571 {"macu.pl", 2, 0x48, mul_reg_opr_opr
, 0},
3573 {"macu.lb", 2, 0x48, mul_reg_opr_opr
, 0},
3574 {"macu.lw", 2, 0x48, mul_reg_opr_opr
, 0},
3575 {"macu.lp", 2, 0x48, mul_reg_opr_opr
, 0},
3576 {"macu.ll", 2, 0x48, mul_reg_opr_opr
, 0},
3581 {"mods", 2, 0x38, mul_reg_reg_reg
, 0},
3582 {"modu", 2, 0x38, mul_reg_reg_reg
, 0},
3584 {"mods.b", 2, 0x38, mul_reg_reg_opr
, 0},
3585 {"mods.w", 2, 0x38, mul_reg_reg_opr
, 0},
3586 {"mods.l", 2, 0x38, mul_reg_reg_opr
, 0},
3588 {"modu.b", 2, 0x38, mul_reg_reg_opr
, 0},
3589 {"modu.w", 2, 0x38, mul_reg_reg_opr
, 0},
3590 {"modu.l", 2, 0x38, mul_reg_reg_opr
, 0},
3592 {"mods.b", 2, 0x38, mul_reg_reg_imm
, 0},
3593 {"mods.w", 2, 0x38, mul_reg_reg_imm
, 0},
3594 {"mods.l", 2, 0x38, mul_reg_reg_imm
, 0},
3596 {"modu.b", 2, 0x38, mul_reg_reg_imm
, 0},
3597 {"modu.w", 2, 0x38, mul_reg_reg_imm
, 0},
3598 {"modu.l", 2, 0x38, mul_reg_reg_imm
, 0},
3600 {"mods.bb", 2, 0x38, mul_reg_opr_opr
, 0},
3601 {"mods.bw", 2, 0x38, mul_reg_opr_opr
, 0},
3602 {"mods.bp", 2, 0x38, mul_reg_opr_opr
, 0},
3603 {"mods.bl", 2, 0x38, mul_reg_opr_opr
, 0},
3605 {"mods.wb", 2, 0x38, mul_reg_opr_opr
, 0},
3606 {"mods.ww", 2, 0x38, mul_reg_opr_opr
, 0},
3607 {"mods.wp", 2, 0x38, mul_reg_opr_opr
, 0},
3608 {"mods.wl", 2, 0x38, mul_reg_opr_opr
, 0},
3610 {"mods.pb", 2, 0x38, mul_reg_opr_opr
, 0},
3611 {"mods.pw", 2, 0x38, mul_reg_opr_opr
, 0},
3612 {"mods.pp", 2, 0x38, mul_reg_opr_opr
, 0},
3613 {"mods.pl", 2, 0x38, mul_reg_opr_opr
, 0},
3615 {"mods.lb", 2, 0x38, mul_reg_opr_opr
, 0},
3616 {"mods.lw", 2, 0x38, mul_reg_opr_opr
, 0},
3617 {"mods.lp", 2, 0x38, mul_reg_opr_opr
, 0},
3618 {"mods.ll", 2, 0x38, mul_reg_opr_opr
, 0},
3620 {"modu.bb", 2, 0x38, mul_reg_opr_opr
, 0},
3621 {"modu.bw", 2, 0x38, mul_reg_opr_opr
, 0},
3622 {"modu.bp", 2, 0x38, mul_reg_opr_opr
, 0},
3623 {"modu.bl", 2, 0x38, mul_reg_opr_opr
, 0},
3625 {"modu.wb", 2, 0x38, mul_reg_opr_opr
, 0},
3626 {"modu.ww", 2, 0x38, mul_reg_opr_opr
, 0},
3627 {"modu.wp", 2, 0x38, mul_reg_opr_opr
, 0},
3628 {"modu.wl", 2, 0x38, mul_reg_opr_opr
, 0},
3630 {"modu.pb", 2, 0x38, mul_reg_opr_opr
, 0},
3631 {"modu.pw", 2, 0x38, mul_reg_opr_opr
, 0},
3632 {"modu.pp", 2, 0x38, mul_reg_opr_opr
, 0},
3633 {"modu.pl", 2, 0x38, mul_reg_opr_opr
, 0},
3635 {"modu.lb", 2, 0x38, mul_reg_opr_opr
, 0},
3636 {"modu.lw", 2, 0x38, mul_reg_opr_opr
, 0},
3637 {"modu.lp", 2, 0x38, mul_reg_opr_opr
, 0},
3638 {"modu.ll", 2, 0x38, mul_reg_opr_opr
, 0}
3642 /* Gas line assembler entry point. */
3644 /* This is the main entry point for the machine-dependent assembler. str
3645 points to a machine-dependent instruction. This function is supposed to
3646 emit the frags/bytes it assembles to. */
3648 md_assemble (char *str
)
3655 fail_line_pointer
= NULL
;
3657 /* Find the opcode end and get the opcode in 'name'. The opcode is forced
3658 lower case (the opcode table only has lower case op-codes). */
3659 for (op_start
= op_end
= str
;
3660 *op_end
&& !is_end_of_line
[(int)*op_end
] && *op_end
!= ' ';
3663 name
[nlen
] = TOLOWER (op_start
[nlen
]);
3665 gas_assert (nlen
< sizeof (name
) - 1);
3671 as_bad (_("No instruction or missing opcode."));
3675 input_line_pointer
= skip_whites (op_end
);
3678 for (i
= 0; i
< sizeof (opcodes
) / sizeof (opcodes
[0]); ++i
)
3680 const struct instruction
*opc
= opcodes
+ i
;
3681 if (0 == strcmp (name
, opc
->name
))
3683 if (opc
->parse_operands (opc
))
3689 as_bad (_("Invalid instruction: \"%s\""), str
);
3690 as_bad (_("First invalid token: \"%s\""), fail_line_pointer
);
3691 while (*input_line_pointer
++)
3699 /* Relocation, relaxation and frag conversions. */
3701 /* PC-relative offsets are relative to the start of the
3702 next instruction. That is, the address of the offset, plus its
3703 size, since the offset is always the last part of the insn. */
3705 md_pcrel_from (fixS
*fixP
)
3707 long ret
= fixP
->fx_size
+ fixP
->fx_frag
->fr_address
;
3708 if (fixP
->fx_addsy
&& S_IS_DEFINED (fixP
->fx_addsy
))
3709 ret
+= fixP
->fx_where
;
3715 /* We need a port-specific relaxation function to cope with sym2 - sym1
3716 relative expressions with both symbols in the same segment (but not
3717 necessarily in the same frag as this insn), for example:
3718 ldab sym2-(sym1-2),pc
3720 The offset can be 5, 9 or 16 bits long. */
3723 s12z_relax_frag (segT seg ATTRIBUTE_UNUSED
, fragS
*fragP ATTRIBUTE_UNUSED
,
3724 long stretch ATTRIBUTE_UNUSED
)
3730 md_convert_frag (bfd
*abfd ATTRIBUTE_UNUSED
, asection
*sec ATTRIBUTE_UNUSED
,
3731 fragS
*fragP ATTRIBUTE_UNUSED
)
3735 /* On an ELF system, we can't relax a weak symbol. The weak symbol
3736 can be overridden at final link time by a non weak symbol. We can
3737 relax externally visible symbol because there is no shared library
3738 and such symbol can't be overridden (unless they are weak). */
3740 /* Force truly undefined symbols to their maximum size, and generally set up
3741 the frag list to be relaxed. */
3743 md_estimate_size_before_relax (fragS
*fragP ATTRIBUTE_UNUSED
, asection
*segment ATTRIBUTE_UNUSED
)
3749 /* If while processing a fixup, a reloc really needs to be created
3750 then it is done here. */
3752 tc_gen_reloc (asection
*section
, fixS
*fixp
)
3754 arelent
*reloc
= XNEW (arelent
);
3755 reloc
->sym_ptr_ptr
= XNEW (asymbol
*);
3756 *reloc
->sym_ptr_ptr
= symbol_get_bfdsym (fixp
->fx_addsy
);
3757 reloc
->address
= fixp
->fx_frag
->fr_address
+ fixp
->fx_where
;
3758 reloc
->howto
= bfd_reloc_type_lookup (stdoutput
, fixp
->fx_r_type
);
3759 if (reloc
->howto
== (reloc_howto_type
*) NULL
)
3761 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
3762 _("Relocation %d is not supported by object file format."),
3763 (int) fixp
->fx_r_type
);
3767 if (0 == (section
->flags
& SEC_CODE
))
3768 reloc
->addend
= fixp
->fx_offset
;
3770 reloc
->addend
= fixp
->fx_addnumber
;
3775 /* See whether we need to force a relocation into the output file. */
3777 tc_s12z_force_relocation (fixS
*fixP
)
3779 return generic_force_reloc (fixP
);
3782 /* Here we decide which fixups can be adjusted to make them relative
3783 to the beginning of the section instead of the symbol. Basically
3784 we need to make sure that the linker relaxation is done
3785 correctly, so in some cases we force the original symbol to be
3788 tc_s12z_fix_adjustable (fixS
*fixP ATTRIBUTE_UNUSED
)
3794 md_apply_fix (fixS
*fixP
, valueT
*valP
, segT seg ATTRIBUTE_UNUSED
)
3798 if (fixP
->fx_addsy
== (symbolS
*) NULL
)
3801 /* We don't actually support subtracting a symbol. */
3802 if (fixP
->fx_subsy
!= (symbolS
*) NULL
)
3803 as_bad_where (fixP
->fx_file
, fixP
->fx_line
, _("Expression too complex."));
3806 Patch the instruction with the resolved operand. Elf relocation
3807 info will also be generated to take care of linker/loader fixups.
3809 char *where
= fixP
->fx_frag
->fr_literal
+ fixP
->fx_where
;
3811 switch (fixP
->fx_r_type
)
3814 ((bfd_byte
*) where
)[0] = (bfd_byte
) value
;
3817 bfd_putb24 ((bfd_vma
) value
, (unsigned char *) where
);
3820 bfd_putb32 ((bfd_vma
) value
, (unsigned char *) where
);
3822 case BFD_RELOC_16_PCREL
:
3823 if (value
< -0x8000 || value
> 0x7FFF)
3824 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
3825 _("Value out of 16-bit range."));
3827 bfd_putb16 ((bfd_vma
) value
| 0x8000, (unsigned char *) where
);
3831 as_fatal (_("Line %d: unknown relocation type: 0x%x."),
3832 fixP
->fx_line
, fixP
->fx_r_type
);
3836 /* Set the ELF specific flags. */
3838 s12z_elf_final_processing (void)