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 "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 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 valueT value
= exp
->X_add_number
;
619 if (value
< (0x1U
<< 14))
626 else if (value
< (0x1U
<< 19))
629 if (value
& (0x1U
<< 17))
631 if (value
& (0x1U
<< 16))
634 buffer
[1] = value
>> 8;
641 buffer
[1] = value
>> 16;
642 buffer
[2] = value
>> 8;
650 fail_line_pointer
= input_line_pointer
;
651 input_line_pointer
= ilp
;
656 lex_offset (long *val
)
659 char *p
= input_line_pointer
;
664 if (*p
!= '+' && *p
!= '-')
667 bool negative
= (*p
== '-');
671 *val
= strtol (p
, &end
, 0);
676 input_line_pointer
= end
;
687 typedef int (*parse_operand_func
) (const struct instruction
*);
693 /* The "page" to which the instruction belongs.
694 This is also only a hint. Some instructions might have modes in both
698 /* This is a hint - and only a hint - about the opcode of the instruction.
699 The parse_operand_func is free to ignore it.
703 parse_operand_func parse_operands
;
705 /* Some instructions can be encoded with a different opcode */
710 no_operands (const struct instruction
*insn
)
712 if (*input_line_pointer
!= '\0')
714 as_bad (_("Garbage at end of instruction"));
718 char *f
= s12z_new_insn (insn
->page
);
720 number_to_chars_bigendian (f
++, PAGE2_PREBYTE
, 1);
722 number_to_chars_bigendian (f
++, insn
->opc
, 1);
727 /* Emit the code for an OPR address mode operand */
729 emit_opr (char *f
, const uint8_t *buffer
, int n_bytes
, expressionS
*exp
)
732 number_to_chars_bigendian (f
++, buffer
[0], 1);
733 if (exp
->X_op
!= O_absent
&& exp
->X_op
!= O_constant
)
735 fix_new_exp (frag_now
,
736 f
- frag_now
->fr_literal
,
742 for (i
= 1; i
< n_bytes
; ++i
)
743 number_to_chars_bigendian (f
++, buffer
[i
], 1);
748 /* Emit the code for a 24 bit direct address operand */
750 emit_ext24 (char *f
, long v
)
752 number_to_chars_bigendian (f
, v
, 3);
758 opr (const struct instruction
*insn
)
763 if (lex_opr (buffer
, &n_bytes
, &exp
))
765 /* Large constant direct values are more efficiently encoded as ext24 mode.
766 Otherwise a decision has to be deferred to a relax. */
767 if (exp
.X_op
== O_constant
769 && insn
->alt_opc
!= 0)
771 char *f
= s12z_new_insn (4);
773 /* I don't think there are any instances of page 2 opcodes in this case */
774 gas_assert (insn
->page
== 1);
776 number_to_chars_bigendian (f
++, insn
->alt_opc
, 1);
778 emit_ext24 (f
, exp
.X_add_number
);
782 char *f
= s12z_new_insn (n_bytes
+ 1);
783 number_to_chars_bigendian (f
++, insn
->opc
, 1);
785 emit_opr (f
, buffer
, n_bytes
, &exp
);
793 /* Parse a 15 bit offset, as an expression.
794 LONG_DISPLACEMENT will be set to true if the offset is wider than 7 bits.
797 lex_15_bit_offset (bool *long_displacement
, expressionS
*exp
)
799 char *ilp
= input_line_pointer
;
802 if (lex_offset (&val
))
804 exp
->X_op
= O_absent
;
805 exp
->X_add_number
= val
;
807 else if (lex_expression (exp
))
809 if (exp
->X_op
== O_constant
)
811 val
= exp
->X_add_number
;
815 /* If a symbol was parsed we don't know the displacement.
816 We have to assume it is long, and relax it later if possible. */
817 *long_displacement
= true;
823 exp
->X_op
= O_absent
;
827 if (val
> 0x3FFF || val
< -0x4000)
829 as_fatal (_("Offset is outside of 15 bit range"));
833 *long_displacement
= (val
> 63 || val
< -64);
838 fail_line_pointer
= input_line_pointer
;
839 input_line_pointer
= ilp
;
844 emit_15_bit_offset (char *f
, int where
, expressionS
*exp
)
847 if (exp
->X_op
!= O_absent
&& exp
->X_op
!= O_constant
)
849 exp
->X_add_number
+= where
;
850 fixS
*fix
= fix_new_exp (frag_now
,
851 f
- frag_now
->fr_literal
,
856 fix
->fx_addnumber
= where
- 2;
860 long val
= exp
->X_add_number
;
861 bool long_displacement
= (val
> 63 || val
< -64);
862 if (long_displacement
)
867 number_to_chars_bigendian (f
++, val
, long_displacement
? 2 : 1);
872 rel (const struct instruction
*insn
)
874 bool long_displacement
;
877 if (! lex_15_bit_offset (&long_displacement
, &exp
))
880 char *f
= s12z_new_insn (long_displacement
? 3 : 2);
881 number_to_chars_bigendian (f
++, insn
->opc
, 1);
882 emit_15_bit_offset (f
, 3, &exp
);
887 reg_inh (const struct instruction
*insn
)
890 if (lex_reg_name (REG_BIT_Dn
, ®
))
892 char *f
= s12z_new_insn (insn
->page
);
894 number_to_chars_bigendian (f
++, PAGE2_PREBYTE
, 1);
896 number_to_chars_bigendian (f
++, insn
->opc
+ reg
, 1);
904 /* Special case for CLR X and CLR Y */
906 clr_xy (const struct instruction
*insn ATTRIBUTE_UNUSED
)
909 if (lex_reg_name (REG_BIT_XY
, ®
))
911 char *f
= s12z_new_insn (1);
912 number_to_chars_bigendian (f
, 0x9a + reg
- REG_X
, 1);
919 /* Some instructions have a suffix like ".l", ".b", ".w" etc
920 which indicates the size of the operands. */
922 size_from_suffix (const struct instruction
*insn
, int idx
)
924 const char *dot
= strchr (insn
->name
, '.');
930 switch (dot
[1 + idx
])
945 as_fatal (_("Bad size"));
952 mul_reg_reg_reg (const struct instruction
*insn
)
954 char *ilp
= input_line_pointer
;
957 if (!lex_reg_name (REG_BIT_Dn
, &Dd
))
960 if (!lex_match (','))
964 if (!lex_reg_name (REG_BIT_Dn
, &Dj
))
967 if (!lex_match (','))
971 if (!lex_reg_name (REG_BIT_Dn
, &Dk
))
974 char *f
= s12z_new_insn (insn
->page
+ 1);
976 number_to_chars_bigendian (f
++, PAGE2_PREBYTE
, 1);
978 number_to_chars_bigendian (f
++, insn
->opc
+ Dd
, 1);
979 const char *dot
= strchrnul (insn
->name
, '.');
990 as_fatal (_("BAD MUL"));
997 number_to_chars_bigendian (f
++, mb
, 1);
1002 fail_line_pointer
= input_line_pointer
;
1003 input_line_pointer
= ilp
;
1009 mul_reg_reg_imm (const struct instruction
*insn
)
1011 char *ilp
= input_line_pointer
;
1014 if (!lex_reg_name (REG_BIT_Dn
, &Dd
))
1017 if (!lex_match (','))
1021 if (!lex_reg_name (REG_BIT_Dn
, &Dj
))
1024 if (!lex_match (','))
1028 if (!lex_imm (&imm
))
1032 int size
= size_from_suffix (insn
, 0);
1034 char *f
= s12z_new_insn (insn
->page
+ 1 + size
);
1035 if (insn
->page
== 2)
1036 number_to_chars_bigendian (f
++, PAGE2_PREBYTE
, 1);
1038 number_to_chars_bigendian (f
++, insn
->opc
+ Dd
, 1);
1040 const char *dot
= strchrnul (insn
->name
, '.');
1050 as_fatal (_("BAD MUL"));
1057 number_to_chars_bigendian (f
++, mb
, 1);
1058 number_to_chars_bigendian (f
++, imm
, size
);
1063 fail_line_pointer
= input_line_pointer
;
1064 input_line_pointer
= ilp
;
1070 mul_reg_reg_opr (const struct instruction
*insn
)
1072 char *ilp
= input_line_pointer
;
1075 if (!lex_reg_name (REG_BIT_Dn
, &Dd
))
1078 if (!lex_match (','))
1082 if (!lex_reg_name (REG_BIT_Dn
, &Dj
))
1085 if (!lex_match (','))
1091 if (!lex_opr (buffer
, &n_bytes
, &exp
))
1094 int size
= size_from_suffix (insn
, 0);
1096 char *f
= s12z_new_insn (insn
->page
+ 1 + n_bytes
);
1097 if (insn
->page
== 2)
1098 number_to_chars_bigendian (f
++, PAGE2_PREBYTE
, 1);
1100 number_to_chars_bigendian (f
++, insn
->opc
+ Dd
, 1);
1102 const char *dot
= strchrnul (insn
->name
, '.');
1112 as_fatal (_("BAD MUL"));
1119 number_to_chars_bigendian (f
++, mb
, 1);
1121 emit_opr (f
, buffer
, n_bytes
, &exp
);
1126 fail_line_pointer
= input_line_pointer
;
1127 input_line_pointer
= ilp
;
1132 mul_reg_opr_opr (const struct instruction
*insn
)
1134 char *ilp
= input_line_pointer
;
1137 if (!lex_reg_name (REG_BIT_Dn
, &Dd
))
1140 if (!lex_match (','))
1146 if (!lex_opr (buffer1
, &n_bytes1
, &exp1
))
1149 if (!lex_match (','))
1155 if (!lex_opr (buffer2
, &n_bytes2
, &exp2
))
1158 int size1
= size_from_suffix (insn
, 0);
1159 int size2
= size_from_suffix (insn
, 1);
1161 char *f
= s12z_new_insn (insn
->page
+ 1 + n_bytes1
+ n_bytes2
);
1162 if (insn
->page
== 2)
1163 number_to_chars_bigendian (f
++, PAGE2_PREBYTE
, 1);
1165 number_to_chars_bigendian (f
++, insn
->opc
+ Dd
, 1);
1167 const char *dot
= strchrnul (insn
->name
, '.');
1177 as_fatal (_("BAD MUL"));
1181 mb
|= (size1
- 1) << 4;
1182 mb
|= (size2
- 1) << 2;
1183 number_to_chars_bigendian (f
++, mb
, 1);
1185 f
= emit_opr (f
, buffer1
, n_bytes1
, &exp1
);
1186 f
= emit_opr (f
, buffer2
, n_bytes2
, &exp2
);
1191 fail_line_pointer
= input_line_pointer
;
1192 input_line_pointer
= ilp
;
1197 #define REG_BIT_GRP0 \
1198 ((0x1U << REG_D2) | \
1199 (0x1U << REG_D3) | \
1200 (0x1U << REG_CCH) | \
1201 (0x1U << REG_CCL) | \
1202 (0x1U << REG_D0) | \
1205 #define REG_BIT_GRP1 \
1206 ((0x1U << REG_D4) | \
1207 (0x1U << REG_D5) | \
1208 (0x1U << REG_D6) | \
1209 (0x1U << REG_D7) | \
1213 static const uint8_t reg_map
[] =
1233 lex_reg_list (uint16_t grp
, uint16_t *reg_bits
)
1235 if (lex_match (','))
1238 if (!lex_reg_name (grp
, ®
))
1240 *reg_bits
|= 0x1u
<< reg
;
1241 lex_reg_list (grp
, reg_bits
);
1249 psh_pull (const struct instruction
*insn
)
1252 (0 == strcmp ("pul", insn
->name
)) ? 0x80: 0x00;
1254 if (lex_match_string ("all16b"))
1258 else if (lex_match_string ("all"))
1265 if (!lex_reg_name (REG_BIT_GRP1
| REG_BIT_GRP0
, ®1
))
1267 uint16_t admitted_group
= 0;
1269 if ((0x1U
<< reg1
) & REG_BIT_GRP1
)
1270 admitted_group
= REG_BIT_GRP1
;
1271 else if ((0x1U
<< reg1
) & REG_BIT_GRP0
)
1272 admitted_group
= REG_BIT_GRP0
;
1274 uint16_t reg_bits
= 0x1 << reg1
;
1275 if (!lex_reg_list (admitted_group
, ®_bits
))
1278 if (reg_bits
& REG_BIT_GRP1
)
1282 for (i
= 0; i
< 16; ++i
)
1284 if (reg_bits
& (0x1u
<< i
))
1289 char *f
= s12z_new_insn (2);
1290 number_to_chars_bigendian (f
++, insn
->opc
, 1);
1291 number_to_chars_bigendian (f
++, pb
, 1);
1295 fail_line_pointer
= input_line_pointer
;
1301 tfr (const struct instruction
*insn
)
1304 if (!lex_reg_name (~0, ®1
))
1307 if (!lex_match (','))
1311 if (!lex_reg_name (~0, ®2
))
1314 if ((0 == strcasecmp ("sex", insn
->name
))
1315 || (0 == strcasecmp ("zex", insn
->name
)))
1317 if (registers
[reg1
].bytes
>= registers
[reg2
].bytes
)
1319 as_bad (_("Source register for %s must be smaller that the destination register"),
1325 char *f
= s12z_new_insn (1 + insn
->page
);
1326 if (insn
->page
== 2)
1327 number_to_chars_bigendian (f
++, PAGE2_PREBYTE
, 1);
1329 number_to_chars_bigendian (f
++, insn
->opc
, 1);
1330 number_to_chars_bigendian (f
++, reg1
<< 4 | reg2
, 1);
1335 fail_line_pointer
= input_line_pointer
;
1340 imm8 (const struct instruction
*insn
)
1343 if (! lex_imm (&imm
))
1345 if (imm
> 127 || imm
< -128)
1347 as_bad (_("Immediate value %ld is out of range for instruction %s"),
1351 char *f
= s12z_new_insn (2);
1352 number_to_chars_bigendian (f
++, insn
->opc
, 1);
1353 number_to_chars_bigendian (f
++, imm
, 1);
1359 reg_imm (const struct instruction
*insn
, int allowed_reg
)
1361 char *ilp
= input_line_pointer
;
1363 if (lex_reg_name (allowed_reg
, ®
))
1365 if (!lex_force_match (','))
1368 if (! lex_imm (&imm
))
1371 short size
= registers
[reg
].bytes
;
1372 char *f
= s12z_new_insn (insn
->page
+ size
);
1373 if (insn
->page
== 2)
1374 number_to_chars_bigendian (f
++, PAGE2_PREBYTE
, 1);
1376 number_to_chars_bigendian (f
++, insn
->opc
+ reg
, 1);
1377 number_to_chars_bigendian (f
++, imm
, size
);
1382 fail_line_pointer
= input_line_pointer
;
1383 input_line_pointer
= ilp
;
1389 regd_imm (const struct instruction
*insn
)
1391 return reg_imm (insn
, REG_BIT_Dn
);
1395 regdxy_imm (const struct instruction
*insn
)
1397 return reg_imm (insn
, REG_BIT_Dn
| REG_BIT_XY
);
1402 regs_imm (const struct instruction
*insn
)
1404 return reg_imm (insn
, 0x1U
<< REG_S
);
1408 trap_imm (const struct instruction
*insn ATTRIBUTE_UNUSED
)
1411 if (! lex_imm (&imm
))
1414 if (imm
< 0x92 || imm
> 0xFF ||
1415 (imm
>= 0xA0 && imm
<= 0xA7) ||
1416 (imm
>= 0xB0 && imm
<= 0xB7))
1418 as_bad (_("trap value %ld is not valid"), imm
);
1423 char *f
= s12z_new_insn (2);
1424 number_to_chars_bigendian (f
++, PAGE2_PREBYTE
, 1);
1425 number_to_chars_bigendian (f
++, imm
& 0xFF, 1);
1432 fail_line_pointer
= input_line_pointer
;
1438 /* Special one byte instruction CMP X, Y */
1440 regx_regy (const struct instruction
*insn
)
1443 if (lex_reg_name (0x1U
<< REG_X
, ®
))
1445 if (lex_force_match (','))
1447 if (lex_reg_name (0x1U
<< REG_Y
, ®
))
1449 char *f
= s12z_new_insn (1);
1450 number_to_chars_bigendian (f
, insn
->opc
, 1);
1458 /* Special one byte instruction SUB D6, X, Y */
1460 regd6_regx_regy (const struct instruction
*insn
)
1462 char *ilp
= input_line_pointer
;
1464 if (!lex_reg_name (0x1U
<< REG_D6
, ®
))
1467 if (!lex_match (','))
1470 if (!lex_reg_name (0x1U
<< REG_X
, ®
))
1473 if (!lex_match (','))
1476 if (!lex_reg_name (0x1U
<< REG_Y
, ®
))
1479 char *f
= s12z_new_insn (1);
1480 number_to_chars_bigendian (f
, insn
->opc
, 1);
1484 fail_line_pointer
= input_line_pointer
;
1485 input_line_pointer
= ilp
;
1489 /* Special one byte instruction SUB D6, Y, X */
1491 regd6_regy_regx (const struct instruction
*insn
)
1493 char *ilp
= input_line_pointer
;
1495 if (!lex_reg_name (0x1U
<< REG_D6
, ®
))
1498 if (!lex_match (','))
1501 if (!lex_reg_name (0x1U
<< REG_Y
, ®
))
1504 if (!lex_match (','))
1507 if (!lex_reg_name (0x1U
<< REG_X
, ®
))
1510 char *f
= s12z_new_insn (1);
1511 number_to_chars_bigendian (f
, insn
->opc
, 1);
1515 fail_line_pointer
= input_line_pointer
;
1516 input_line_pointer
= ilp
;
1521 reg_opr (const struct instruction
*insn
, int allowed_regs
)
1523 char *ilp
= input_line_pointer
;
1525 if (lex_reg_name (allowed_regs
, ®
))
1527 if (!lex_force_match (','))
1533 if (lex_opr (buffer
, &n_bytes
, &exp
))
1535 /* Large constant direct values are more efficiently encoded as ext24 mode.
1536 Otherwise a decision has to be deferred to a relax. */
1537 if (exp
.X_op
== O_constant
1538 && buffer
[0] == 0xFA
1539 && insn
->alt_opc
!= 0)
1541 char *f
= s12z_new_insn (4);
1543 /* I don't think there are any instances of page 2 opcodes in this case */
1544 gas_assert (insn
->page
== 1);
1546 number_to_chars_bigendian (f
++, insn
->alt_opc
+ reg
, 1);
1548 emit_ext24 (f
, exp
.X_add_number
);
1552 char *f
= s12z_new_insn (n_bytes
+ insn
->page
);
1554 if (insn
->page
== 2)
1555 number_to_chars_bigendian (f
++, PAGE2_PREBYTE
, 1);
1557 number_to_chars_bigendian (f
++, insn
->opc
+ reg
, 1);
1559 emit_opr (f
, buffer
, n_bytes
, &exp
);
1567 fail_line_pointer
= input_line_pointer
;
1568 input_line_pointer
= ilp
;
1574 regdxy_opr (const struct instruction
*insn
)
1576 return reg_opr (insn
, REG_BIT_Dn
| REG_BIT_XY
);
1580 regd_opr (const struct instruction
*insn
)
1582 return reg_opr (insn
, REG_BIT_Dn
);
1587 regs_opr (const struct instruction
*insn
)
1589 return reg_opr (insn
, 0x1U
<< REG_S
);
1593 imm_opr (const struct instruction
*insn
)
1595 char *ilp
= input_line_pointer
;
1597 if (!lex_imm (&imm
))
1600 if (!lex_match (','))
1606 if (!lex_opr (buffer
, &n_bytes
, &exp
))
1609 int size
= size_from_suffix (insn
, 0);
1610 char *f
= s12z_new_insn (1 + n_bytes
+ size
);
1611 number_to_chars_bigendian (f
++, insn
->opc
, 1);
1614 for (i
= 0; i
< size
; ++i
)
1615 number_to_chars_bigendian (f
++, imm
>> (CHAR_BIT
* (size
- i
- 1)), 1);
1617 emit_opr (f
, buffer
, n_bytes
, &exp
);
1622 fail_line_pointer
= input_line_pointer
;
1623 input_line_pointer
= ilp
;
1628 opr_opr (const struct instruction
*insn
)
1630 char *ilp
= input_line_pointer
;
1635 if (!lex_opr (buffer1
, &n_bytes1
, &exp1
))
1639 if (!lex_match (','))
1645 if (!lex_opr (buffer2
, &n_bytes2
, &exp2
))
1648 char *f
= s12z_new_insn (1 + n_bytes1
+ n_bytes2
);
1649 number_to_chars_bigendian (f
++, insn
->opc
, 1);
1651 f
= emit_opr (f
, buffer1
, n_bytes1
, &exp1
);
1652 f
= emit_opr (f
, buffer2
, n_bytes2
, &exp2
);
1657 fail_line_pointer
= input_line_pointer
;
1658 input_line_pointer
= ilp
;
1663 reg67sxy_opr (const struct instruction
*insn
)
1666 if (!lex_reg_name (REG_BIT_XYS
| (0x1U
<< REG_D6
) | (0x1U
<< REG_D7
), ®
))
1669 if (!lex_match (','))
1675 if (!lex_opr (buffer
, &n_bytes
, &exp
))
1678 char *f
= s12z_new_insn (1 + n_bytes
);
1679 number_to_chars_bigendian (f
++, insn
->opc
+ reg
- REG_D6
, 1);
1680 emit_opr (f
, buffer
, n_bytes
, &exp
);
1686 rotate (const struct instruction
*insn
, short dir
)
1691 if (lex_opr (buffer
, &n_bytes
, &exp
))
1693 char *f
= s12z_new_insn (n_bytes
+ 2);
1694 number_to_chars_bigendian (f
++, insn
->opc
, 1);
1695 int size
= size_from_suffix (insn
, 0);
1702 number_to_chars_bigendian (f
++, sb
, 1);
1703 emit_opr (f
, buffer
, n_bytes
, &exp
);
1712 rol (const struct instruction
*insn
)
1714 return rotate (insn
, 1);
1718 ror (const struct instruction
*insn
)
1720 return rotate (insn
, 0);
1724 /* Shift instruction with a register operand and an immediate #1 or #2
1725 left = 1; right = 0;
1726 logical = 0; arithmetic = 1;
1729 lex_shift_reg_imm1 (const struct instruction
*insn
, short type
, short dir
)
1732 This function is highly unusual and a bit wierd!
1733 It first matches the input against a register {d0, d1, ... d7} followed by an immediate
1735 Then, it rewinds the input and parses it again as a OPR.
1737 char *ilp
= input_line_pointer
;
1740 if (!lex_reg_name (REG_BIT_Dn
, &Dd
))
1745 if (!lex_match (','))
1749 if (!lex_imm (&imm
))
1752 if (imm
!= 1 && imm
!= 2)
1754 input_line_pointer
= ilp
;
1756 /* Now parse the first operand again */
1762 if (!lex_opr (buffer
, &n_bytes
, &exp
))
1765 gas_assert (n_bytes
== 1);
1773 char *f
= s12z_new_insn (3);
1774 number_to_chars_bigendian (f
++, insn
->opc
, 1);
1775 number_to_chars_bigendian (f
++, sb
, 1);
1776 emit_opr (f
, buffer
, n_bytes
, &exp
);
1781 fail_line_pointer
= input_line_pointer
;
1782 input_line_pointer
= ilp
;
1786 /* Shift instruction with a register operand.
1787 left = 1; right = 0;
1788 logical = 0; arithmetic = 1; */
1790 lex_shift_reg (const struct instruction
*insn
, short type
, short dir
)
1793 if (!lex_reg_name (REG_BIT_Dn
, &Dd
))
1798 if (!lex_match (','))
1801 if (!lex_reg_name (REG_BIT_Dn
, &Ds
))
1806 if (!lex_match (','))
1814 if (lex_reg_name (REG_BIT_Dn
, &Dn
))
1816 char *f
= s12z_new_insn (3);
1817 number_to_chars_bigendian (f
++, insn
->opc
| Dd
, 1);
1818 number_to_chars_bigendian (f
++, sb
, 1);
1821 number_to_chars_bigendian (f
++, xb
, 1);
1825 else if (lex_imm (&imm
))
1827 if (imm
< 0 || imm
> 31)
1829 as_bad (_("Shift value should be in the range [0,31]"));
1834 if (imm
== 1 || imm
== 2)
1841 sb
|= (imm
& 0x01) << 3;
1844 char *f
= s12z_new_insn (n_bytes
);
1845 number_to_chars_bigendian (f
++, insn
->opc
| Dd
, 1);
1846 number_to_chars_bigendian (f
++, sb
, 1);
1851 number_to_chars_bigendian (f
++, xb
, 1);
1858 fail_line_pointer
= input_line_pointer
;
1863 impute_shift_dir_and_type (const struct instruction
*insn
, short *type
, short *dir
)
1867 switch (insn
->name
[0])
1876 as_fatal (_("Bad shift mode"));
1880 switch (insn
->name
[2])
1889 as_fatal (_("Bad shift *direction"));
1894 /* Shift instruction with a OPR operand */
1896 shift_two_operand (const struct instruction
*insn
)
1899 char *ilp
= input_line_pointer
;
1903 impute_shift_dir_and_type (insn
, &type
, &dir
);
1907 int size
= size_from_suffix (insn
, 0);
1913 if (!lex_opr (buffer
, &n_opr_bytes
, &exp
))
1916 if (!lex_match (','))
1920 if (!lex_imm (&imm
))
1923 if (imm
!= 1 && imm
!= 2)
1929 char *f
= s12z_new_insn (2 + n_opr_bytes
);
1930 number_to_chars_bigendian (f
++, insn
->opc
, 1);
1931 number_to_chars_bigendian (f
++, sb
, 1);
1932 emit_opr (f
, buffer
, n_opr_bytes
, &exp
);
1937 fail_line_pointer
= input_line_pointer
;
1938 input_line_pointer
= ilp
;
1942 /* Shift instruction with a OPR operand */
1944 shift_opr_imm (const struct instruction
*insn
)
1946 char *ilp
= input_line_pointer
;
1950 impute_shift_dir_and_type (insn
, &type
, &dir
);
1953 if (!lex_reg_name (REG_BIT_Dn
, &Dd
))
1956 if (!lex_match (','))
1965 if (!lex_opr (buffer1
, &n_opr_bytes1
, &exp1
))
1968 n_bytes
+= n_opr_bytes1
;
1969 if (!lex_match (','))
1973 int n_opr_bytes2
= 0;
1976 bool immediate
= false;
1981 else if (!lex_opr (buffer2
, &n_opr_bytes2
, &exp2
))
1986 int size
= size_from_suffix (insn
, 0);
1996 if (imm
== 2 || imm
== 1)
2011 n_bytes
+= n_opr_bytes2
;
2015 char *f
= s12z_new_insn (n_bytes
);
2016 number_to_chars_bigendian (f
++, insn
->opc
| Dd
, 1);
2017 number_to_chars_bigendian (f
++, sb
, 1);
2018 f
= emit_opr (f
, buffer1
, n_opr_bytes1
, &exp1
);
2021 if (imm
!= 1 && imm
!= 2)
2023 number_to_chars_bigendian (f
++, 0x70 | (imm
>> 1), 1);
2028 f
= emit_opr (f
, buffer2
, n_opr_bytes2
, &exp2
);
2034 fail_line_pointer
= input_line_pointer
;
2035 input_line_pointer
= ilp
;
2039 /* Shift instruction with a register operand */
2041 shift_reg (const struct instruction
*insn
)
2045 impute_shift_dir_and_type (insn
, &type
, &dir
);
2047 if (lex_shift_reg_imm1 (insn
, type
, dir
))
2050 return lex_shift_reg (insn
, type
, dir
);
2054 bm_regd_imm (const struct instruction
*insn
)
2056 char *ilp
= input_line_pointer
;
2058 if (!lex_reg_name (REG_BIT_Dn
, &Di
))
2061 if (!lex_match (','))
2065 if (!lex_imm (&imm
))
2069 uint8_t bm
= imm
<< 3;
2072 char *f
= s12z_new_insn (2);
2073 number_to_chars_bigendian (f
++, insn
->opc
, 1);
2074 number_to_chars_bigendian (f
++, bm
, 1);
2079 fail_line_pointer
= input_line_pointer
;
2080 input_line_pointer
= ilp
;
2085 bm_opr_reg (const struct instruction
*insn
)
2087 char *ilp
= input_line_pointer
;
2093 if (!lex_opr (buffer
, &n_opr_bytes
, &exp
))
2096 if (!lex_match (','))
2100 if (!lex_reg_name (REG_BIT_Dn
, &Dn
))
2103 uint8_t bm
= Dn
<< 4;
2104 int size
= size_from_suffix (insn
, 0);
2105 bm
|= (size
- 1) << 2;
2108 char *f
= s12z_new_insn (2 + n_opr_bytes
);
2109 number_to_chars_bigendian (f
++, insn
->opc
, 1);
2110 number_to_chars_bigendian (f
++, bm
, 1);
2112 emit_opr (f
, buffer
, n_opr_bytes
, &exp
);
2117 fail_line_pointer
= input_line_pointer
;
2118 input_line_pointer
= ilp
;
2124 bm_opr_imm (const struct instruction
*insn
)
2126 char *ilp
= input_line_pointer
;
2132 if (!lex_opr (buffer
, &n_opr_bytes
, &exp
))
2135 if (!lex_match (','))
2140 if (!lex_imm (&imm
))
2143 int size
= size_from_suffix (insn
, 0);
2145 if (imm
< 0 || imm
>= size
* 8)
2147 as_bad (_("Immediate operand %ld is inappropriate for size of instruction"), imm
);
2156 bm
|= (imm
& 0x07) << 4;
2160 char *f
= s12z_new_insn (2 + n_opr_bytes
);
2161 number_to_chars_bigendian (f
++, insn
->opc
, 1);
2162 number_to_chars_bigendian (f
++, bm
, 1);
2163 emit_opr (f
, buffer
, n_opr_bytes
, &exp
);
2168 fail_line_pointer
= input_line_pointer
;
2169 input_line_pointer
= ilp
;
2175 bm_regd_reg (const struct instruction
*insn
)
2177 char *ilp
= input_line_pointer
;
2179 if (!lex_reg_name (REG_BIT_Dn
, &Di
))
2182 if (!lex_match (','))
2186 if (!lex_reg_name (REG_BIT_Dn
, &Dn
))
2189 uint8_t bm
= Dn
<< 4;
2192 uint8_t xb
= Di
| 0xb8;
2194 char *f
= s12z_new_insn (3);
2195 number_to_chars_bigendian (f
++, insn
->opc
, 1);
2196 number_to_chars_bigendian (f
++, bm
, 1);
2197 number_to_chars_bigendian (f
++, xb
, 1);
2202 fail_line_pointer
= input_line_pointer
;
2203 input_line_pointer
= ilp
;
2212 bf_reg_opr_imm (const struct instruction
*insn
, short ie
)
2214 char *ilp
= input_line_pointer
;
2216 if (!lex_reg_name (REG_BIT_Dn
, &Dd
))
2219 if (!lex_match (','))
2226 if (!lex_opr (buffer
, &n_bytes
, &exp
))
2229 if (!lex_match (','))
2233 if (!lex_imm (&width
))
2236 if (width
< 0 || width
> 31)
2238 as_bad (_("Invalid width value for %s"), insn
->name
);
2242 if (!lex_match (':'))
2246 if (!lex_constant (&offset
))
2249 if (offset
< 0 || offset
> 31)
2251 as_bad (_("Invalid offset value for %s"), insn
->name
);
2255 uint8_t i1
= width
<< 5;
2258 int size
= size_from_suffix (insn
, 0);
2259 uint8_t bb
= ie
? 0x80 : 0x00;
2261 bb
|= (size
- 1) << 2;
2264 char *f
= s12z_new_insn (4 + n_bytes
);
2265 number_to_chars_bigendian (f
++, PAGE2_PREBYTE
, 1);
2266 number_to_chars_bigendian (f
++, 0x08 | Dd
, 1);
2267 number_to_chars_bigendian (f
++, bb
, 1);
2268 number_to_chars_bigendian (f
++, i1
, 1);
2270 emit_opr (f
, buffer
, n_bytes
, &exp
);
2275 fail_line_pointer
= input_line_pointer
;
2276 input_line_pointer
= ilp
;
2282 bf_opr_reg_imm (const struct instruction
*insn
, short ie
)
2284 char *ilp
= input_line_pointer
;
2288 if (!lex_opr (buffer
, &n_bytes
, &exp
))
2291 if (!lex_match (','))
2295 if (!lex_reg_name (REG_BIT_Dn
, &Ds
))
2298 if (!lex_match (','))
2302 if (!lex_imm (&width
))
2305 if (width
< 0 || width
> 31)
2307 as_bad (_("Invalid width value for %s"), insn
->name
);
2311 if (!lex_match (':'))
2315 if (!lex_constant (&offset
))
2318 if (offset
< 0 || offset
> 31)
2320 as_bad (_("Invalid offset value for %s"), insn
->name
);
2324 uint8_t i1
= width
<< 5;
2327 int size
= size_from_suffix (insn
, 0);
2328 uint8_t bb
= ie
? 0x80 : 0x00;
2330 bb
|= (size
- 1) << 2;
2333 char *f
= s12z_new_insn (4 + n_bytes
);
2334 number_to_chars_bigendian (f
++, PAGE2_PREBYTE
, 1);
2335 number_to_chars_bigendian (f
++, 0x08 | Ds
, 1);
2336 number_to_chars_bigendian (f
++, bb
, 1);
2337 number_to_chars_bigendian (f
++, i1
, 1);
2339 emit_opr (f
, buffer
, n_bytes
, &exp
);
2344 fail_line_pointer
= input_line_pointer
;
2345 input_line_pointer
= ilp
;
2352 bf_reg_reg_imm (const struct instruction
*insn
, short ie
)
2354 char *ilp
= input_line_pointer
;
2356 if (!lex_reg_name (REG_BIT_Dn
, &Dd
))
2359 if (!lex_match (','))
2363 if (!lex_reg_name (REG_BIT_Dn
, &Ds
))
2366 if (!lex_match (','))
2370 if (!lex_imm (&width
))
2373 if (width
< 0 || width
> 31)
2375 as_bad (_("Invalid width value for %s"), insn
->name
);
2379 if (!lex_match (':'))
2383 if (!lex_constant (&offset
))
2386 if (offset
< 0 || offset
> 31)
2388 as_bad (_("Invalid offset value for %s"), insn
->name
);
2392 uint8_t bb
= ie
? 0x80 : 0x00;
2397 uint8_t i1
= width
<< 5;
2400 char *f
= s12z_new_insn (4);
2401 number_to_chars_bigendian (f
++, PAGE2_PREBYTE
, 1);
2402 number_to_chars_bigendian (f
++, 0x08 | Dd
, 1);
2403 number_to_chars_bigendian (f
++, bb
, 1);
2404 number_to_chars_bigendian (f
++, i1
, 1);
2409 fail_line_pointer
= input_line_pointer
;
2410 input_line_pointer
= ilp
;
2415 bf_reg_reg_reg (const struct instruction
*insn ATTRIBUTE_UNUSED
, short ie
)
2417 char *ilp
= input_line_pointer
;
2419 if (!lex_reg_name (REG_BIT_Dn
, &Dd
))
2422 if (!lex_match (','))
2426 if (!lex_reg_name (REG_BIT_Dn
, &Ds
))
2429 if (!lex_match (','))
2433 if (!lex_reg_name ((0x01u
<< REG_D2
) |
2440 uint8_t bb
= ie
? 0x80 : 0x00;
2444 char *f
= s12z_new_insn (3);
2445 number_to_chars_bigendian (f
++, PAGE2_PREBYTE
, 1);
2446 number_to_chars_bigendian (f
++, 0x08 | Dd
, 1);
2447 number_to_chars_bigendian (f
++, bb
, 1);
2452 fail_line_pointer
= input_line_pointer
;
2453 input_line_pointer
= ilp
;
2458 bf_opr_reg_reg (const struct instruction
*insn
, short ie
)
2460 char *ilp
= input_line_pointer
;
2465 if (!lex_opr (buffer
, &n_bytes
, &exp
))
2468 if (!lex_match (','))
2473 if (!lex_reg_name (REG_BIT_Dn
, &Ds
))
2476 if (!lex_match (','))
2481 if (!lex_reg_name ((0x01u
<< REG_D2
) |
2488 int size
= size_from_suffix (insn
, 0);
2489 uint8_t bb
= ie
? 0x80 : 0x00;
2492 bb
|= (size
- 1) << 2;
2494 char *f
= s12z_new_insn (3 + n_bytes
);
2495 number_to_chars_bigendian (f
++, PAGE2_PREBYTE
, 1);
2496 number_to_chars_bigendian (f
++, 0x08 | Ds
, 1);
2497 number_to_chars_bigendian (f
++, bb
, 1);
2499 emit_opr (f
, buffer
, n_bytes
, &exp
);
2504 fail_line_pointer
= input_line_pointer
;
2505 input_line_pointer
= ilp
;
2511 bf_reg_opr_reg (const struct instruction
*insn
, short ie
)
2513 char *ilp
= input_line_pointer
;
2515 if (!lex_reg_name (REG_BIT_Dn
, &Dd
))
2518 if (!lex_match (','))
2525 if (!lex_opr (buffer
, &n_bytes
, &exp
))
2528 if (!lex_match (','))
2532 if (!lex_reg_name ((0x01u
<< REG_D2
) |
2539 int size
= size_from_suffix (insn
, 0);
2540 uint8_t bb
= ie
? 0x80 : 0x00;
2543 bb
|= (size
- 1) << 2;
2545 char *f
= s12z_new_insn (3 + n_bytes
);
2546 number_to_chars_bigendian (f
++, PAGE2_PREBYTE
, 1);
2547 number_to_chars_bigendian (f
++, 0x08 | Dd
, 1);
2548 number_to_chars_bigendian (f
++, bb
, 1);
2550 emit_opr (f
, buffer
, n_bytes
, &exp
);
2555 fail_line_pointer
= input_line_pointer
;
2556 input_line_pointer
= ilp
;
2563 bfe_reg_reg_reg (const struct instruction
*insn
)
2565 return bf_reg_reg_reg (insn
, 0);
2569 bfi_reg_reg_reg (const struct instruction
*insn
)
2571 return bf_reg_reg_reg (insn
, 1);
2575 bfe_reg_reg_imm (const struct instruction
*insn
)
2577 return bf_reg_reg_imm (insn
, 0);
2581 bfi_reg_reg_imm (const struct instruction
*insn
)
2583 return bf_reg_reg_imm (insn
, 1);
2588 bfe_reg_opr_reg (const struct instruction
*insn
)
2590 return bf_reg_opr_reg (insn
, 0);
2594 bfi_reg_opr_reg (const struct instruction
*insn
)
2596 return bf_reg_opr_reg (insn
, 1);
2601 bfe_opr_reg_reg (const struct instruction
*insn
)
2603 return bf_opr_reg_reg (insn
, 0);
2607 bfi_opr_reg_reg (const struct instruction
*insn
)
2609 return bf_opr_reg_reg (insn
, 1);
2613 bfe_reg_opr_imm (const struct instruction
*insn
)
2615 return bf_reg_opr_imm (insn
, 0);
2619 bfi_reg_opr_imm (const struct instruction
*insn
)
2621 return bf_reg_opr_imm (insn
, 1);
2625 bfe_opr_reg_imm (const struct instruction
*insn
)
2627 return bf_opr_reg_imm (insn
, 0);
2631 bfi_opr_reg_imm (const struct instruction
*insn
)
2633 return bf_opr_reg_imm (insn
, 1);
2640 tb_reg_rel (const struct instruction
*insn
)
2642 char *ilp
= input_line_pointer
;
2645 if (!lex_reg_name (REG_BIT_Dn
| REG_BIT_XY
, ®
))
2648 if (!lex_match (','))
2651 bool long_displacement
;
2653 if (! lex_15_bit_offset (&long_displacement
, &exp
))
2657 if (reg
== REG_X
|| reg
== REG_Y
)
2668 if (0 == strncmp (insn
->name
+ 2, "ne", 2))
2670 else if (0 == strncmp (insn
->name
+ 2, "eq", 2))
2672 else if (0 == strncmp (insn
->name
+ 2, "pl", 2))
2674 else if (0 == strncmp (insn
->name
+ 2, "mi", 2))
2676 else if (0 == strncmp (insn
->name
+ 2, "gt", 2))
2678 else if (0 == strncmp (insn
->name
+ 2, "le", 2))
2681 switch (insn
->name
[0])
2693 char *f
= s12z_new_insn (long_displacement
? 4 : 3);
2694 number_to_chars_bigendian (f
++, insn
->opc
, 1);
2695 number_to_chars_bigendian (f
++, lb
, 1);
2697 emit_15_bit_offset (f
, 4, &exp
);
2702 fail_line_pointer
= input_line_pointer
;
2703 input_line_pointer
= ilp
;
2709 tb_opr_rel (const struct instruction
*insn
)
2711 char *ilp
= input_line_pointer
;
2716 if (!lex_opr (buffer
, &n_bytes
, &exp
))
2719 if (!lex_match (','))
2722 bool long_displacement
;
2724 if (! lex_15_bit_offset (&long_displacement
, &exp2
))
2729 if (0 == strncmp (insn
->name
+ 2, "ne", 2))
2731 else if (0 == strncmp (insn
->name
+ 2, "eq", 2))
2733 else if (0 == strncmp (insn
->name
+ 2, "pl", 2))
2735 else if (0 == strncmp (insn
->name
+ 2, "mi", 2))
2737 else if (0 == strncmp (insn
->name
+ 2, "gt", 2))
2739 else if (0 == strncmp (insn
->name
+ 2, "le", 2))
2742 switch (insn
->name
[0])
2754 int size
= size_from_suffix (insn
, 0);
2758 char *f
= s12z_new_insn (n_bytes
+ (long_displacement
? 4 : 3));
2759 number_to_chars_bigendian (f
++, insn
->opc
, 1);
2760 number_to_chars_bigendian (f
++, lb
, 1);
2761 f
= emit_opr (f
, buffer
, n_bytes
, &exp
);
2763 emit_15_bit_offset (f
, n_bytes
+ 4, &exp2
);
2768 fail_line_pointer
= input_line_pointer
;
2769 input_line_pointer
= ilp
;
2777 test_br_reg_reg_rel (const struct instruction
*insn
)
2779 char *ilp
= input_line_pointer
;
2782 if (!lex_reg_name (REG_BIT_Dn
, &Di
))
2785 if (!lex_match (','))
2790 if (!lex_reg_name (REG_BIT_Dn
, &Dn
))
2793 if (!lex_match (','))
2797 bool long_displacement
;
2799 if (! lex_15_bit_offset (&long_displacement
, &exp
))
2808 char *f
= s12z_new_insn (long_displacement
? 5 : 4);
2809 number_to_chars_bigendian (f
++, insn
->opc
, 1);
2810 number_to_chars_bigendian (f
++, bm
, 1);
2811 number_to_chars_bigendian (f
++, xb
, 1);
2813 emit_15_bit_offset (f
, 5, &exp
);
2818 fail_line_pointer
= input_line_pointer
;
2819 input_line_pointer
= ilp
;
2824 test_br_opr_reg_rel (const struct instruction
*insn
)
2826 char *ilp
= input_line_pointer
;
2831 if (!lex_opr (buffer
, &n_bytes
, &exp
))
2834 if (!lex_match (','))
2838 if (!lex_reg_name (REG_BIT_Dn
, &Dn
))
2841 if (!lex_match (','))
2846 int size
= size_from_suffix (insn
, 0);
2847 bm
|= (size
-1) << 2;
2849 bool long_displacement
;
2852 if (! lex_15_bit_offset (&long_displacement
, &exp2
))
2855 int n
= n_bytes
+ (long_displacement
? 4 : 3);
2856 char *f
= s12z_new_insn (n
);
2857 number_to_chars_bigendian (f
++, insn
->opc
, 1);
2858 number_to_chars_bigendian (f
++, bm
, 1);
2859 f
= emit_opr (f
, buffer
, n_bytes
, &exp
);
2861 emit_15_bit_offset (f
, n
, &exp2
);
2866 fail_line_pointer
= input_line_pointer
;
2867 input_line_pointer
= ilp
;
2873 test_br_opr_imm_rel (const struct instruction
*insn
)
2875 char *ilp
= input_line_pointer
;
2880 if (!lex_opr (buffer
, &n_bytes
, &exp
))
2883 if (!lex_match (','))
2887 if (!lex_imm (&imm
))
2890 if (imm
< 0 || imm
> 31)
2893 if (!lex_match (','))
2896 bool long_displacement
;
2898 if (! lex_15_bit_offset (&long_displacement
, &exp2
))
2901 int size
= size_from_suffix (insn
, 0);
2904 bm
|= (imm
& 0x07) << 4;
2905 bm
|= (imm
>> 3) & 0x03;
2911 char *f
= s12z_new_insn (n_bytes
+ (long_displacement
? 4 : 3));
2912 number_to_chars_bigendian (f
++, insn
->opc
, 1);
2913 number_to_chars_bigendian (f
++, bm
, 1);
2914 f
= emit_opr (f
, buffer
, n_bytes
, &exp
);
2916 emit_15_bit_offset (f
, n_bytes
+ 4, &exp2
);
2921 fail_line_pointer
= input_line_pointer
;
2922 input_line_pointer
= ilp
;
2928 test_br_reg_imm_rel (const struct instruction
*insn
)
2930 char *ilp
= input_line_pointer
;
2933 if (!lex_reg_name (REG_BIT_Dn
, &Di
))
2936 if (!lex_match (','))
2940 if (!lex_imm (&imm
))
2943 if (imm
< 0 || imm
> 31)
2947 if (!lex_match (','))
2950 bool long_displacement
;
2952 if (! lex_15_bit_offset (&long_displacement
, &exp
))
2958 char *f
= s12z_new_insn (long_displacement
? 4 : 3);
2959 number_to_chars_bigendian (f
++, insn
->opc
, 1);
2960 number_to_chars_bigendian (f
++, bm
, 1);
2962 emit_15_bit_offset (f
, 4, &exp
);
2967 fail_line_pointer
= input_line_pointer
;
2968 input_line_pointer
= ilp
;
2975 static const struct instruction opcodes
[] = {
2976 {"bgnd", 1, 0x00, no_operands
, 0},
2977 {"nop", 1, 0x01, no_operands
, 0},
2979 {"brclr", 1, 0x02, test_br_reg_reg_rel
, 0},
2980 {"brset", 1, 0x03, test_br_reg_reg_rel
, 0},
2982 {"brclr", 1, 0x02, test_br_reg_imm_rel
, 0},
2983 {"brset", 1, 0x03, test_br_reg_imm_rel
, 0},
2985 {"brclr.b", 1, 0x02, test_br_opr_reg_rel
, 0},
2986 {"brclr.w", 1, 0x02, test_br_opr_reg_rel
, 0},
2987 {"brclr.l", 1, 0x02, test_br_opr_reg_rel
, 0},
2989 {"brset.b", 1, 0x03, test_br_opr_reg_rel
, 0},
2990 {"brset.w", 1, 0x03, test_br_opr_reg_rel
, 0},
2991 {"brset.l", 1, 0x03, test_br_opr_reg_rel
, 0},
2993 {"brclr.b", 1, 0x02, test_br_opr_imm_rel
, 0},
2994 {"brclr.w", 1, 0x02, test_br_opr_imm_rel
, 0},
2995 {"brclr.l", 1, 0x02, test_br_opr_imm_rel
, 0},
2997 {"brset.b", 1, 0x03, test_br_opr_imm_rel
, 0},
2998 {"brset.w", 1, 0x03, test_br_opr_imm_rel
, 0},
2999 {"brset.l", 1, 0x03, test_br_opr_imm_rel
, 0},
3001 {"psh", 1, 0x04, psh_pull
, 0},
3002 {"pul", 1, 0x04, psh_pull
, 0},
3004 {"rts", 1, 0x05, no_operands
, 0},
3005 {"lea", 1, 0x06, reg67sxy_opr
, 0},
3007 {"dbne", 1, 0x0b, tb_reg_rel
, 0},
3008 {"dbeq", 1, 0x0b, tb_reg_rel
, 0},
3009 {"dbpl", 1, 0x0b, tb_reg_rel
, 0},
3010 {"dbmi", 1, 0x0b, tb_reg_rel
, 0},
3011 {"dbgt", 1, 0x0b, tb_reg_rel
, 0},
3012 {"dble", 1, 0x0b, tb_reg_rel
, 0},
3014 {"dbne.b", 1, 0x0b, tb_opr_rel
, 0},
3015 {"dbeq.b", 1, 0x0b, tb_opr_rel
, 0},
3016 {"dbpl.b", 1, 0x0b, tb_opr_rel
, 0},
3017 {"dbmi.b", 1, 0x0b, tb_opr_rel
, 0},
3018 {"dbgt.b", 1, 0x0b, tb_opr_rel
, 0},
3019 {"dble.b", 1, 0x0b, tb_opr_rel
, 0},
3021 {"dbne.w", 1, 0x0b, tb_opr_rel
, 0},
3022 {"dbeq.w", 1, 0x0b, tb_opr_rel
, 0},
3023 {"dbpl.w", 1, 0x0b, tb_opr_rel
, 0},
3024 {"dbmi.w", 1, 0x0b, tb_opr_rel
, 0},
3025 {"dbgt.w", 1, 0x0b, tb_opr_rel
, 0},
3026 {"dble.w", 1, 0x0b, tb_opr_rel
, 0},
3028 {"dbne.p", 1, 0x0b, tb_opr_rel
, 0},
3029 {"dbeq.p", 1, 0x0b, tb_opr_rel
, 0},
3030 {"dbpl.p", 1, 0x0b, tb_opr_rel
, 0},
3031 {"dbmi.p", 1, 0x0b, tb_opr_rel
, 0},
3032 {"dbgt.p", 1, 0x0b, tb_opr_rel
, 0},
3033 {"dble.p", 1, 0x0b, tb_opr_rel
, 0},
3035 {"dbne.l", 1, 0x0b, tb_opr_rel
, 0},
3036 {"dbeq.l", 1, 0x0b, tb_opr_rel
, 0},
3037 {"dbpl.l", 1, 0x0b, tb_opr_rel
, 0},
3038 {"dbmi.l", 1, 0x0b, tb_opr_rel
, 0},
3039 {"dbgt.l", 1, 0x0b, tb_opr_rel
, 0},
3040 {"dble.l", 1, 0x0b, tb_opr_rel
, 0},
3042 {"tbne", 1, 0x0b, tb_reg_rel
, 0},
3043 {"tbeq", 1, 0x0b, tb_reg_rel
, 0},
3044 {"tbpl", 1, 0x0b, tb_reg_rel
, 0},
3045 {"tbmi", 1, 0x0b, tb_reg_rel
, 0},
3046 {"tbgt", 1, 0x0b, tb_reg_rel
, 0},
3047 {"tble", 1, 0x0b, tb_reg_rel
, 0},
3049 {"tbne.b", 1, 0x0b, tb_opr_rel
, 0},
3050 {"tbeq.b", 1, 0x0b, tb_opr_rel
, 0},
3051 {"tbpl.b", 1, 0x0b, tb_opr_rel
, 0},
3052 {"tbmi.b", 1, 0x0b, tb_opr_rel
, 0},
3053 {"tbgt.b", 1, 0x0b, tb_opr_rel
, 0},
3054 {"tble.b", 1, 0x0b, tb_opr_rel
, 0},
3056 {"tbne.w", 1, 0x0b, tb_opr_rel
, 0},
3057 {"tbeq.w", 1, 0x0b, tb_opr_rel
, 0},
3058 {"tbpl.w", 1, 0x0b, tb_opr_rel
, 0},
3059 {"tbmi.w", 1, 0x0b, tb_opr_rel
, 0},
3060 {"tbgt.w", 1, 0x0b, tb_opr_rel
, 0},
3061 {"tble.w", 1, 0x0b, tb_opr_rel
, 0},
3063 {"tbne.p", 1, 0x0b, tb_opr_rel
, 0},
3064 {"tbeq.p", 1, 0x0b, tb_opr_rel
, 0},
3065 {"tbpl.p", 1, 0x0b, tb_opr_rel
, 0},
3066 {"tbmi.p", 1, 0x0b, tb_opr_rel
, 0},
3067 {"tbgt.p", 1, 0x0b, tb_opr_rel
, 0},
3068 {"tble.p", 1, 0x0b, tb_opr_rel
, 0},
3070 {"tbne.l", 1, 0x0b, tb_opr_rel
, 0},
3071 {"tbeq.l", 1, 0x0b, tb_opr_rel
, 0},
3072 {"tbpl.l", 1, 0x0b, tb_opr_rel
, 0},
3073 {"tbmi.l", 1, 0x0b, tb_opr_rel
, 0},
3074 {"tbgt.l", 1, 0x0b, tb_opr_rel
, 0},
3075 {"tble.l", 1, 0x0b, tb_opr_rel
, 0},
3077 {"mov.b", 1, 0x0c, imm_opr
, 0},
3078 {"mov.w", 1, 0x0d, imm_opr
, 0},
3079 {"mov.p", 1, 0x0e, imm_opr
, 0},
3080 {"mov.l", 1, 0x0f, imm_opr
, 0},
3082 {"rol", 1, 0x10, rol
, 0},
3083 {"rol.b", 1, 0x10, rol
, 0},
3084 {"rol.w", 1, 0x10, rol
, 0},
3085 {"rol.p", 1, 0x10, rol
, 0},
3086 {"rol.l", 1, 0x10, rol
, 0},
3088 {"ror", 1, 0x10, ror
, 0},
3089 {"ror.b", 1, 0x10, ror
, 0},
3090 {"ror.w", 1, 0x10, ror
, 0},
3091 {"ror.p", 1, 0x10, ror
, 0},
3092 {"ror.l", 1, 0x10, ror
, 0},
3094 {"lsl", 1, 0x10, shift_reg
, 0},
3095 {"lsr", 1, 0x10, shift_reg
, 0},
3096 {"asl", 1, 0x10, shift_reg
, 0},
3097 {"asr", 1, 0x10, shift_reg
, 0},
3099 {"lsl.b", 1, 0x10, shift_two_operand
, 0},
3100 {"lsl.w", 1, 0x10, shift_two_operand
, 0},
3101 {"lsl.p", 1, 0x10, shift_two_operand
, 0},
3102 {"lsl.l", 1, 0x10, shift_two_operand
, 0},
3103 {"asl.b", 1, 0x10, shift_two_operand
, 0},
3104 {"asl.w", 1, 0x10, shift_two_operand
, 0},
3105 {"asl.p", 1, 0x10, shift_two_operand
, 0},
3106 {"asl.l", 1, 0x10, shift_two_operand
, 0},
3108 {"lsr.b", 1, 0x10, shift_two_operand
, 0},
3109 {"lsr.w", 1, 0x10, shift_two_operand
, 0},
3110 {"lsr.p", 1, 0x10, shift_two_operand
, 0},
3111 {"lsr.l", 1, 0x10, shift_two_operand
, 0},
3112 {"asr.b", 1, 0x10, shift_two_operand
, 0},
3113 {"asr.w", 1, 0x10, shift_two_operand
, 0},
3114 {"asr.p", 1, 0x10, shift_two_operand
, 0},
3115 {"asr.l", 1, 0x10, shift_two_operand
, 0},
3117 {"lsl.b", 1, 0x10, shift_opr_imm
, 0},
3118 {"lsl.w", 1, 0x10, shift_opr_imm
, 0},
3119 {"lsl.p", 1, 0x10, shift_opr_imm
, 0},
3120 {"lsl.l", 1, 0x10, shift_opr_imm
, 0},
3121 {"asl.b", 1, 0x10, shift_opr_imm
, 0},
3122 {"asl.w", 1, 0x10, shift_opr_imm
, 0},
3123 {"asl.p", 1, 0x10, shift_opr_imm
, 0},
3124 {"asl.l", 1, 0x10, shift_opr_imm
, 0},
3126 {"lsr.b", 1, 0x10, shift_opr_imm
, 0},
3127 {"lsr.w", 1, 0x10, shift_opr_imm
, 0},
3128 {"lsr.p", 1, 0x10, shift_opr_imm
, 0},
3129 {"lsr.l", 1, 0x10, shift_opr_imm
, 0},
3130 {"asr.b", 1, 0x10, shift_opr_imm
, 0},
3131 {"asr.w", 1, 0x10, shift_opr_imm
, 0},
3132 {"asr.p", 1, 0x10, shift_opr_imm
, 0},
3133 {"asr.l", 1, 0x10, shift_opr_imm
, 0},
3135 {"mov.b", 1, 0x1c, opr_opr
, 0},
3136 {"mov.w", 1, 0x1d, opr_opr
, 0},
3137 {"mov.p", 1, 0x1e, opr_opr
, 0},
3138 {"mov.l", 1, 0x1f, opr_opr
, 0},
3140 {"bra", 1, 0x20, rel
, 0},
3141 {"bsr", 1, 0x21, rel
, 0},
3142 {"bhi", 1, 0x22, rel
, 0},
3143 {"bls", 1, 0x23, rel
, 0},
3144 {"bcc", 1, 0x24, rel
, 0},
3145 {"bcs", 1, 0x25, rel
, 0},
3146 {"bne", 1, 0x26, rel
, 0},
3147 {"beq", 1, 0x27, rel
, 0},
3148 {"bvc", 1, 0x28, rel
, 0},
3149 {"bvs", 1, 0x29, rel
, 0},
3150 {"bpl", 1, 0x2a, rel
, 0},
3151 {"bmi", 1, 0x2b, rel
, 0},
3152 {"bge", 1, 0x2c, rel
, 0},
3153 {"blt", 1, 0x2d, rel
, 0},
3154 {"bgt", 1, 0x2e, rel
, 0},
3155 {"ble", 1, 0x2f, rel
, 0},
3157 {"inc", 1, 0x30, reg_inh
, 0},
3158 {"clr", 1, 0x38, reg_inh
, 0},
3159 {"dec", 1, 0x40, reg_inh
, 0},
3161 {"muls", 1, 0x48, mul_reg_reg_reg
, 0},
3162 {"mulu", 1, 0x48, mul_reg_reg_reg
, 0},
3164 {"muls.b", 1, 0x48, mul_reg_reg_opr
, 0},
3165 {"muls.w", 1, 0x48, mul_reg_reg_opr
, 0},
3166 {"muls.l", 1, 0x48, mul_reg_reg_opr
, 0},
3168 {"mulu.b", 1, 0x48, mul_reg_reg_opr
, 0},
3169 {"mulu.w", 1, 0x48, mul_reg_reg_opr
, 0},
3170 {"mulu.l", 1, 0x48, mul_reg_reg_opr
, 0},
3172 {"muls.b", 1, 0x48, mul_reg_reg_imm
, 0},
3173 {"muls.w", 1, 0x48, mul_reg_reg_imm
, 0},
3174 {"muls.l", 1, 0x48, mul_reg_reg_imm
, 0},
3176 {"mulu.b", 1, 0x48, mul_reg_reg_imm
, 0},
3177 {"mulu.w", 1, 0x48, mul_reg_reg_imm
, 0},
3178 {"mulu.l", 1, 0x48, mul_reg_reg_imm
, 0},
3180 {"muls.bb", 1, 0x48, mul_reg_opr_opr
, 0},
3181 {"muls.bw", 1, 0x48, mul_reg_opr_opr
, 0},
3182 {"muls.bp", 1, 0x48, mul_reg_opr_opr
, 0},
3183 {"muls.bl", 1, 0x48, mul_reg_opr_opr
, 0},
3185 {"muls.wb", 1, 0x48, mul_reg_opr_opr
, 0},
3186 {"muls.ww", 1, 0x48, mul_reg_opr_opr
, 0},
3187 {"muls.wp", 1, 0x48, mul_reg_opr_opr
, 0},
3188 {"muls.wl", 1, 0x48, mul_reg_opr_opr
, 0},
3190 {"muls.pb", 1, 0x48, mul_reg_opr_opr
, 0},
3191 {"muls.pw", 1, 0x48, mul_reg_opr_opr
, 0},
3192 {"muls.pp", 1, 0x48, mul_reg_opr_opr
, 0},
3193 {"muls.pl", 1, 0x48, mul_reg_opr_opr
, 0},
3195 {"muls.lb", 1, 0x48, mul_reg_opr_opr
, 0},
3196 {"muls.lw", 1, 0x48, mul_reg_opr_opr
, 0},
3197 {"muls.lp", 1, 0x48, mul_reg_opr_opr
, 0},
3198 {"muls.ll", 1, 0x48, mul_reg_opr_opr
, 0},
3200 {"mulu.bb", 1, 0x48, mul_reg_opr_opr
, 0},
3201 {"mulu.bw", 1, 0x48, mul_reg_opr_opr
, 0},
3202 {"mulu.bp", 1, 0x48, mul_reg_opr_opr
, 0},
3203 {"mulu.bl", 1, 0x48, mul_reg_opr_opr
, 0},
3205 {"mulu.wb", 1, 0x48, mul_reg_opr_opr
, 0},
3206 {"mulu.ww", 1, 0x48, mul_reg_opr_opr
, 0},
3207 {"mulu.wp", 1, 0x48, mul_reg_opr_opr
, 0},
3208 {"mulu.wl", 1, 0x48, mul_reg_opr_opr
, 0},
3210 {"mulu.pb", 1, 0x48, mul_reg_opr_opr
, 0},
3211 {"mulu.pw", 1, 0x48, mul_reg_opr_opr
, 0},
3212 {"mulu.pp", 1, 0x48, mul_reg_opr_opr
, 0},
3213 {"mulu.pl", 1, 0x48, mul_reg_opr_opr
, 0},
3215 {"mulu.lb", 1, 0x48, mul_reg_opr_opr
, 0},
3216 {"mulu.lw", 1, 0x48, mul_reg_opr_opr
, 0},
3217 {"mulu.lp", 1, 0x48, mul_reg_opr_opr
, 0},
3218 {"mulu.ll", 1, 0x48, mul_reg_opr_opr
, 0},
3220 {"add", 1, 0x50, regd_imm
, 0},
3221 {"and", 1, 0x58, regd_imm
, 0},
3223 {"add", 1, 0x60, regd_opr
, 0},
3224 {"and", 1, 0x68, regd_opr
, 0},
3226 {"sub", 1, 0x70, regd_imm
, 0},
3227 {"or", 1, 0x78, regd_imm
, 0},
3229 {"sub", 1, 0x80, regd_opr
, 0},
3230 {"or", 1, 0x88, regd_opr
, 0},
3232 {"ld", 1, 0x90, regdxy_imm
, 0},
3234 {"clr", 1, 0x9a, clr_xy
, 0},
3235 {"tfr", 1, 0x9e, tfr
, 0},
3236 {"zex", 1, 0x9e, tfr
, 0},
3238 {"ld", 1, 0xa0, regdxy_opr
, 0xb0},
3240 {"jmp", 1, 0xaa, opr
, 0xba},
3241 {"jsr", 1, 0xab, opr
, 0xbb},
3243 {"exg", 1, 0xae, tfr
, 0},
3244 {"sex", 1, 0xae, tfr
, 0},
3246 {"st", 1, 0xc0, regdxy_opr
, 0xd0},
3248 {"andcc", 1, 0xce, imm8
, 0},
3249 {"orcc", 1, 0xde, imm8
, 0},
3251 {"inc.b", 1, 0x9c, opr
, 0},
3252 {"inc.w", 1, 0x9d, opr
, 0},
3253 {"inc.l", 1, 0x9f, opr
, 0},
3255 {"dec.b", 1, 0xac, opr
, 0},
3256 {"dec.w", 1, 0xad, opr
, 0},
3257 {"dec.l", 1, 0xaf, opr
, 0},
3259 {"clr.b", 1, 0xbc, opr
, 0},
3260 {"clr.w", 1, 0xbd, opr
, 0},
3261 {"clr.p", 1, 0xbe, opr
, 0},
3262 {"clr.l", 1, 0xbf, opr
, 0},
3264 {"com.b", 1, 0xcc, opr
, 0},
3265 {"com.w", 1, 0xcd, opr
, 0},
3266 {"com.l", 1, 0xcf, opr
, 0},
3268 {"neg.b", 1, 0xdc, opr
, 0},
3269 {"neg.w", 1, 0xdd, opr
, 0},
3270 {"neg.l", 1, 0xdf, opr
, 0},
3272 {"bclr", 1, 0xec, bm_regd_imm
, 0},
3273 {"bset", 1, 0xed, bm_regd_imm
, 0},
3274 {"btgl", 1, 0xee, bm_regd_imm
, 0},
3276 {"bclr", 1, 0xec, bm_regd_reg
, 0},
3277 {"bset", 1, 0xed, bm_regd_reg
, 0},
3278 {"btgl", 1, 0xee, bm_regd_reg
, 0},
3280 {"bclr.b", 1, 0xec, bm_opr_imm
, 0},
3281 {"bclr.w", 1, 0xec, bm_opr_imm
, 0},
3282 {"bclr.l", 1, 0xec, bm_opr_imm
, 0},
3284 {"bset.b", 1, 0xed, bm_opr_imm
, 0},
3285 {"bset.w", 1, 0xed, bm_opr_imm
, 0},
3286 {"bset.l", 1, 0xed, bm_opr_imm
, 0},
3288 {"btgl.b", 1, 0xee, bm_opr_imm
, 0},
3289 {"btgl.w", 1, 0xee, bm_opr_imm
, 0},
3290 {"btgl.l", 1, 0xee, bm_opr_imm
, 0},
3292 {"bclr.b", 1, 0xec, bm_opr_reg
, 0},
3293 {"bclr.w", 1, 0xec, bm_opr_reg
, 0},
3294 {"bclr.l", 1, 0xec, bm_opr_reg
, 0},
3296 {"bset.b", 1, 0xed, bm_opr_reg
, 0},
3297 {"bset.w", 1, 0xed, bm_opr_reg
, 0},
3298 {"bset.l", 1, 0xed, bm_opr_reg
, 0},
3300 {"btgl.b", 1, 0xee, bm_opr_reg
, 0},
3301 {"btgl.w", 1, 0xee, bm_opr_reg
, 0},
3302 {"btgl.l", 1, 0xee, bm_opr_reg
, 0},
3304 {"cmp", 1, 0xe0, regdxy_imm
, 0},
3305 {"cmp", 1, 0xf0, regdxy_opr
, 0},
3307 {"cmp", 1, 0xfc, regx_regy
, 0},
3308 {"sub", 1, 0xfd, regd6_regx_regy
, 0},
3309 {"sub", 1, 0xfe, regd6_regy_regx
, 0},
3311 {"swi", 1, 0xff, no_operands
, 0},
3315 /* The -10 below is a kludge. The opcode is in fact 0x00 */
3316 {"ld", 2, -10, regs_opr
, 0},
3318 /* The -9 below is a kludge. The opcode is in fact 0x01 */
3319 {"st", 2, -9, regs_opr
, 0},
3321 /* The -8 below is a kludge. The opcode is in fact 0x02 */
3322 {"cmp", 2, -8, regs_opr
, 0},
3324 /* The -7 below is a kludge. The opcode is in fact 0x03 */
3325 {"ld", 2, -7, regs_imm
, 0},
3327 /* The -6 below is a kludge. The opcode is in fact 0x04 */
3328 {"cmp", 2, -6, regs_imm
, 0},
3330 {"bfext", 2, 0x08, bfe_reg_reg_reg
, 0},
3331 {"bfext", 2, 0x08, bfe_reg_reg_imm
, 0},
3332 {"bfext.b", 2, 0x08, bfe_reg_opr_reg
, 0},
3333 {"bfext.w", 2, 0x08, bfe_reg_opr_reg
, 0},
3334 {"bfext.p", 2, 0x08, bfe_reg_opr_reg
, 0},
3335 {"bfext.l", 2, 0x08, bfe_reg_opr_reg
, 0},
3336 {"bfext.b", 2, 0x08, bfe_opr_reg_reg
, 0},
3337 {"bfext.w", 2, 0x08, bfe_opr_reg_reg
, 0},
3338 {"bfext.p", 2, 0x08, bfe_opr_reg_reg
, 0},
3339 {"bfext.l", 2, 0x08, bfe_opr_reg_reg
, 0},
3340 {"bfext.b", 2, 0x08, bfe_reg_opr_imm
, 0},
3341 {"bfext.w", 2, 0x08, bfe_reg_opr_imm
, 0},
3342 {"bfext.p", 2, 0x08, bfe_reg_opr_imm
, 0},
3343 {"bfext.l", 2, 0x08, bfe_reg_opr_imm
, 0},
3344 {"bfext.b", 2, 0x08, bfe_opr_reg_imm
, 0},
3345 {"bfext.w", 2, 0x08, bfe_opr_reg_imm
, 0},
3346 {"bfext.p", 2, 0x08, bfe_opr_reg_imm
, 0},
3347 {"bfext.l", 2, 0x08, bfe_opr_reg_imm
, 0},
3350 {"bfins", 2, 0x08, bfi_reg_reg_reg
, 0},
3351 {"bfins", 2, 0x08, bfi_reg_reg_imm
, 0},
3352 {"bfins.b", 2, 0x08, bfi_reg_opr_reg
, 0},
3353 {"bfins.w", 2, 0x08, bfi_reg_opr_reg
, 0},
3354 {"bfins.p", 2, 0x08, bfi_reg_opr_reg
, 0},
3355 {"bfins.l", 2, 0x08, bfi_reg_opr_reg
, 0},
3356 {"bfins.b", 2, 0x08, bfi_opr_reg_reg
, 0},
3357 {"bfins.w", 2, 0x08, bfi_opr_reg_reg
, 0},
3358 {"bfins.p", 2, 0x08, bfi_opr_reg_reg
, 0},
3359 {"bfins.l", 2, 0x08, bfi_opr_reg_reg
, 0},
3360 {"bfins.b", 2, 0x08, bfi_reg_opr_imm
, 0},
3361 {"bfins.w", 2, 0x08, bfi_reg_opr_imm
, 0},
3362 {"bfins.p", 2, 0x08, bfi_reg_opr_imm
, 0},
3363 {"bfins.l", 2, 0x08, bfi_reg_opr_imm
, 0},
3364 {"bfins.b", 2, 0x08, bfi_opr_reg_imm
, 0},
3365 {"bfins.w", 2, 0x08, bfi_opr_reg_imm
, 0},
3366 {"bfins.p", 2, 0x08, bfi_opr_reg_imm
, 0},
3367 {"bfins.l", 2, 0x08, bfi_opr_reg_imm
, 0},
3370 {"minu", 2, 0x10, regd_opr
, 0},
3371 {"maxu", 2, 0x18, regd_opr
, 0},
3372 {"mins", 2, 0x20, regd_opr
, 0},
3373 {"maxs", 2, 0x28, regd_opr
, 0},
3375 {"clb", 2, 0x91, tfr
, 0},
3377 {"trap", 2, 0x00, trap_imm
, 0},
3378 {"abs", 2, 0x40, reg_inh
, 0},
3379 {"sat", 2, 0xa0, reg_inh
, 0},
3381 {"rti", 2, 0x90, no_operands
, 0},
3382 {"stop", 2, 0x05, no_operands
, 0},
3383 {"wai", 2, 0x06, no_operands
, 0},
3384 {"sys", 2, 0x07, no_operands
, 0},
3386 {"bit", 2, 0x58, regd_imm
, 0},
3387 {"bit", 2, 0x68, regd_opr
, 0},
3389 {"adc", 2, 0x50, regd_imm
, 0},
3390 {"adc", 2, 0x60, regd_opr
, 0},
3392 {"sbc", 2, 0x70, regd_imm
, 0},
3393 {"eor", 2, 0x78, regd_imm
, 0},
3395 {"sbc", 2, 0x80, regd_opr
, 0},
3396 {"eor", 2, 0x88, regd_opr
, 0},
3398 {"divs", 2, 0x30, mul_reg_reg_reg
, 0},
3399 {"divu", 2, 0x30, mul_reg_reg_reg
, 0},
3401 {"divs.b", 2, 0x30, mul_reg_reg_opr
, 0},
3402 {"divs.w", 2, 0x30, mul_reg_reg_opr
, 0},
3403 {"divs.l", 2, 0x30, mul_reg_reg_opr
, 0},
3405 {"divu.b", 2, 0x30, mul_reg_reg_opr
, 0},
3406 {"divu.w", 2, 0x30, mul_reg_reg_opr
, 0},
3407 {"divu.l", 2, 0x30, mul_reg_reg_opr
, 0},
3409 {"divs.b", 2, 0x30, mul_reg_reg_imm
, 0},
3410 {"divs.w", 2, 0x30, mul_reg_reg_imm
, 0},
3411 {"divs.l", 2, 0x30, mul_reg_reg_imm
, 0},
3413 {"divu.b", 2, 0x30, mul_reg_reg_imm
, 0},
3414 {"divu.w", 2, 0x30, mul_reg_reg_imm
, 0},
3415 {"divu.l", 2, 0x30, mul_reg_reg_imm
, 0},
3417 {"divs.bb", 2, 0x30, mul_reg_opr_opr
, 0},
3418 {"divs.bw", 2, 0x30, mul_reg_opr_opr
, 0},
3419 {"divs.bp", 2, 0x30, mul_reg_opr_opr
, 0},
3420 {"divs.bl", 2, 0x30, mul_reg_opr_opr
, 0},
3422 {"divs.wb", 2, 0x30, mul_reg_opr_opr
, 0},
3423 {"divs.ww", 2, 0x30, mul_reg_opr_opr
, 0},
3424 {"divs.wp", 2, 0x30, mul_reg_opr_opr
, 0},
3425 {"divs.wl", 2, 0x30, mul_reg_opr_opr
, 0},
3427 {"divs.pb", 2, 0x30, mul_reg_opr_opr
, 0},
3428 {"divs.pw", 2, 0x30, mul_reg_opr_opr
, 0},
3429 {"divs.pp", 2, 0x30, mul_reg_opr_opr
, 0},
3430 {"divs.pl", 2, 0x30, mul_reg_opr_opr
, 0},
3432 {"divs.lb", 2, 0x30, mul_reg_opr_opr
, 0},
3433 {"divs.lw", 2, 0x30, mul_reg_opr_opr
, 0},
3434 {"divs.lp", 2, 0x30, mul_reg_opr_opr
, 0},
3435 {"divs.ll", 2, 0x30, mul_reg_opr_opr
, 0},
3437 {"divu.bb", 2, 0x30, mul_reg_opr_opr
, 0},
3438 {"divu.bw", 2, 0x30, mul_reg_opr_opr
, 0},
3439 {"divu.bp", 2, 0x30, mul_reg_opr_opr
, 0},
3440 {"divu.bl", 2, 0x30, mul_reg_opr_opr
, 0},
3442 {"divu.wb", 2, 0x30, mul_reg_opr_opr
, 0},
3443 {"divu.ww", 2, 0x30, mul_reg_opr_opr
, 0},
3444 {"divu.wp", 2, 0x30, mul_reg_opr_opr
, 0},
3445 {"divu.wl", 2, 0x30, mul_reg_opr_opr
, 0},
3447 {"divu.pb", 2, 0x30, mul_reg_opr_opr
, 0},
3448 {"divu.pw", 2, 0x30, mul_reg_opr_opr
, 0},
3449 {"divu.pp", 2, 0x30, mul_reg_opr_opr
, 0},
3450 {"divu.pl", 2, 0x30, mul_reg_opr_opr
, 0},
3452 {"divu.lb", 2, 0x30, mul_reg_opr_opr
, 0},
3453 {"divu.lw", 2, 0x30, mul_reg_opr_opr
, 0},
3454 {"divu.lp", 2, 0x30, mul_reg_opr_opr
, 0},
3455 {"divu.ll", 2, 0x30, mul_reg_opr_opr
, 0},
3459 {"qmuls", 2, 0xb0, mul_reg_reg_reg
, 0},
3460 {"qmulu", 2, 0xb0, mul_reg_reg_reg
, 0},
3462 {"qmuls.b", 2, 0xb0, mul_reg_reg_opr
, 0},
3463 {"qmuls.w", 2, 0xb0, mul_reg_reg_opr
, 0},
3464 {"qmuls.l", 2, 0xb0, mul_reg_reg_opr
, 0},
3466 {"qmulu.b", 2, 0xb0, mul_reg_reg_opr
, 0},
3467 {"qmulu.w", 2, 0xb0, mul_reg_reg_opr
, 0},
3468 {"qmulu.l", 2, 0xb0, mul_reg_reg_opr
, 0},
3470 {"qmuls.b", 2, 0xb0, mul_reg_reg_imm
, 0},
3471 {"qmuls.w", 2, 0xb0, mul_reg_reg_imm
, 0},
3472 {"qmuls.l", 2, 0xb0, mul_reg_reg_imm
, 0},
3474 {"qmulu.b", 2, 0xb0, mul_reg_reg_imm
, 0},
3475 {"qmulu.w", 2, 0xb0, mul_reg_reg_imm
, 0},
3476 {"qmulu.l", 2, 0xb0, mul_reg_reg_imm
, 0},
3478 {"qmuls.bb", 2, 0xb0, mul_reg_opr_opr
, 0},
3479 {"qmuls.bw", 2, 0xb0, mul_reg_opr_opr
, 0},
3480 {"qmuls.bp", 2, 0xb0, mul_reg_opr_opr
, 0},
3481 {"qmuls.bl", 2, 0xb0, mul_reg_opr_opr
, 0},
3483 {"qmuls.wb", 2, 0xb0, mul_reg_opr_opr
, 0},
3484 {"qmuls.ww", 2, 0xb0, mul_reg_opr_opr
, 0},
3485 {"qmuls.wp", 2, 0xb0, mul_reg_opr_opr
, 0},
3486 {"qmuls.wl", 2, 0xb0, mul_reg_opr_opr
, 0},
3488 {"qmuls.pb", 2, 0xb0, mul_reg_opr_opr
, 0},
3489 {"qmuls.pw", 2, 0xb0, mul_reg_opr_opr
, 0},
3490 {"qmuls.pp", 2, 0xb0, mul_reg_opr_opr
, 0},
3491 {"qmuls.pl", 2, 0xb0, mul_reg_opr_opr
, 0},
3493 {"qmuls.lb", 2, 0xb0, mul_reg_opr_opr
, 0},
3494 {"qmuls.lw", 2, 0xb0, mul_reg_opr_opr
, 0},
3495 {"qmuls.lp", 2, 0xb0, mul_reg_opr_opr
, 0},
3496 {"qmuls.ll", 2, 0xb0, mul_reg_opr_opr
, 0},
3498 {"qmulu.bb", 2, 0xb0, mul_reg_opr_opr
, 0},
3499 {"qmulu.bw", 2, 0xb0, mul_reg_opr_opr
, 0},
3500 {"qmulu.bp", 2, 0xb0, mul_reg_opr_opr
, 0},
3501 {"qmulu.bl", 2, 0xb0, mul_reg_opr_opr
, 0},
3503 {"qmulu.wb", 2, 0xb0, mul_reg_opr_opr
, 0},
3504 {"qmulu.ww", 2, 0xb0, mul_reg_opr_opr
, 0},
3505 {"qmulu.wp", 2, 0xb0, mul_reg_opr_opr
, 0},
3506 {"qmulu.wl", 2, 0xb0, mul_reg_opr_opr
, 0},
3508 {"qmulu.pb", 2, 0xb0, mul_reg_opr_opr
, 0},
3509 {"qmulu.pw", 2, 0xb0, mul_reg_opr_opr
, 0},
3510 {"qmulu.pp", 2, 0xb0, mul_reg_opr_opr
, 0},
3511 {"qmulu.pl", 2, 0xb0, mul_reg_opr_opr
, 0},
3513 {"qmulu.lb", 2, 0xb0, mul_reg_opr_opr
, 0},
3514 {"qmulu.lw", 2, 0xb0, mul_reg_opr_opr
, 0},
3515 {"qmulu.lp", 2, 0xb0, mul_reg_opr_opr
, 0},
3516 {"qmulu.ll", 2, 0xb0, mul_reg_opr_opr
, 0},
3521 {"macs", 2, 0x48, mul_reg_reg_reg
, 0},
3522 {"macu", 2, 0x48, mul_reg_reg_reg
, 0},
3524 {"macs.b", 2, 0x48, mul_reg_reg_opr
, 0},
3525 {"macs.w", 2, 0x48, mul_reg_reg_opr
, 0},
3526 {"macs.l", 2, 0x48, mul_reg_reg_opr
, 0},
3528 {"macu.b", 2, 0x48, mul_reg_reg_opr
, 0},
3529 {"macu.w", 2, 0x48, mul_reg_reg_opr
, 0},
3530 {"macu.l", 2, 0x48, mul_reg_reg_opr
, 0},
3532 {"macs.b", 2, 0x48, mul_reg_reg_imm
, 0},
3533 {"macs.w", 2, 0x48, mul_reg_reg_imm
, 0},
3534 {"macs.l", 2, 0x48, mul_reg_reg_imm
, 0},
3536 {"macu.b", 2, 0x48, mul_reg_reg_imm
, 0},
3537 {"macu.w", 2, 0x48, mul_reg_reg_imm
, 0},
3538 {"macu.l", 2, 0x48, mul_reg_reg_imm
, 0},
3540 {"macs.bb", 2, 0x48, mul_reg_opr_opr
, 0},
3541 {"macs.bw", 2, 0x48, mul_reg_opr_opr
, 0},
3542 {"macs.bp", 2, 0x48, mul_reg_opr_opr
, 0},
3543 {"macs.bl", 2, 0x48, mul_reg_opr_opr
, 0},
3545 {"macs.wb", 2, 0x48, mul_reg_opr_opr
, 0},
3546 {"macs.ww", 2, 0x48, mul_reg_opr_opr
, 0},
3547 {"macs.wp", 2, 0x48, mul_reg_opr_opr
, 0},
3548 {"macs.wl", 2, 0x48, mul_reg_opr_opr
, 0},
3550 {"macs.pb", 2, 0x48, mul_reg_opr_opr
, 0},
3551 {"macs.pw", 2, 0x48, mul_reg_opr_opr
, 0},
3552 {"macs.pp", 2, 0x48, mul_reg_opr_opr
, 0},
3553 {"macs.pl", 2, 0x48, mul_reg_opr_opr
, 0},
3555 {"macs.lb", 2, 0x48, mul_reg_opr_opr
, 0},
3556 {"macs.lw", 2, 0x48, mul_reg_opr_opr
, 0},
3557 {"macs.lp", 2, 0x48, mul_reg_opr_opr
, 0},
3558 {"macs.ll", 2, 0x48, mul_reg_opr_opr
, 0},
3560 {"macu.bb", 2, 0x48, mul_reg_opr_opr
, 0},
3561 {"macu.bw", 2, 0x48, mul_reg_opr_opr
, 0},
3562 {"macu.bp", 2, 0x48, mul_reg_opr_opr
, 0},
3563 {"macu.bl", 2, 0x48, mul_reg_opr_opr
, 0},
3565 {"macu.wb", 2, 0x48, mul_reg_opr_opr
, 0},
3566 {"macu.ww", 2, 0x48, mul_reg_opr_opr
, 0},
3567 {"macu.wp", 2, 0x48, mul_reg_opr_opr
, 0},
3568 {"macu.wl", 2, 0x48, mul_reg_opr_opr
, 0},
3570 {"macu.pb", 2, 0x48, mul_reg_opr_opr
, 0},
3571 {"macu.pw", 2, 0x48, mul_reg_opr_opr
, 0},
3572 {"macu.pp", 2, 0x48, mul_reg_opr_opr
, 0},
3573 {"macu.pl", 2, 0x48, mul_reg_opr_opr
, 0},
3575 {"macu.lb", 2, 0x48, mul_reg_opr_opr
, 0},
3576 {"macu.lw", 2, 0x48, mul_reg_opr_opr
, 0},
3577 {"macu.lp", 2, 0x48, mul_reg_opr_opr
, 0},
3578 {"macu.ll", 2, 0x48, mul_reg_opr_opr
, 0},
3583 {"mods", 2, 0x38, mul_reg_reg_reg
, 0},
3584 {"modu", 2, 0x38, mul_reg_reg_reg
, 0},
3586 {"mods.b", 2, 0x38, mul_reg_reg_opr
, 0},
3587 {"mods.w", 2, 0x38, mul_reg_reg_opr
, 0},
3588 {"mods.l", 2, 0x38, mul_reg_reg_opr
, 0},
3590 {"modu.b", 2, 0x38, mul_reg_reg_opr
, 0},
3591 {"modu.w", 2, 0x38, mul_reg_reg_opr
, 0},
3592 {"modu.l", 2, 0x38, mul_reg_reg_opr
, 0},
3594 {"mods.b", 2, 0x38, mul_reg_reg_imm
, 0},
3595 {"mods.w", 2, 0x38, mul_reg_reg_imm
, 0},
3596 {"mods.l", 2, 0x38, mul_reg_reg_imm
, 0},
3598 {"modu.b", 2, 0x38, mul_reg_reg_imm
, 0},
3599 {"modu.w", 2, 0x38, mul_reg_reg_imm
, 0},
3600 {"modu.l", 2, 0x38, mul_reg_reg_imm
, 0},
3602 {"mods.bb", 2, 0x38, mul_reg_opr_opr
, 0},
3603 {"mods.bw", 2, 0x38, mul_reg_opr_opr
, 0},
3604 {"mods.bp", 2, 0x38, mul_reg_opr_opr
, 0},
3605 {"mods.bl", 2, 0x38, mul_reg_opr_opr
, 0},
3607 {"mods.wb", 2, 0x38, mul_reg_opr_opr
, 0},
3608 {"mods.ww", 2, 0x38, mul_reg_opr_opr
, 0},
3609 {"mods.wp", 2, 0x38, mul_reg_opr_opr
, 0},
3610 {"mods.wl", 2, 0x38, mul_reg_opr_opr
, 0},
3612 {"mods.pb", 2, 0x38, mul_reg_opr_opr
, 0},
3613 {"mods.pw", 2, 0x38, mul_reg_opr_opr
, 0},
3614 {"mods.pp", 2, 0x38, mul_reg_opr_opr
, 0},
3615 {"mods.pl", 2, 0x38, mul_reg_opr_opr
, 0},
3617 {"mods.lb", 2, 0x38, mul_reg_opr_opr
, 0},
3618 {"mods.lw", 2, 0x38, mul_reg_opr_opr
, 0},
3619 {"mods.lp", 2, 0x38, mul_reg_opr_opr
, 0},
3620 {"mods.ll", 2, 0x38, mul_reg_opr_opr
, 0},
3622 {"modu.bb", 2, 0x38, mul_reg_opr_opr
, 0},
3623 {"modu.bw", 2, 0x38, mul_reg_opr_opr
, 0},
3624 {"modu.bp", 2, 0x38, mul_reg_opr_opr
, 0},
3625 {"modu.bl", 2, 0x38, mul_reg_opr_opr
, 0},
3627 {"modu.wb", 2, 0x38, mul_reg_opr_opr
, 0},
3628 {"modu.ww", 2, 0x38, mul_reg_opr_opr
, 0},
3629 {"modu.wp", 2, 0x38, mul_reg_opr_opr
, 0},
3630 {"modu.wl", 2, 0x38, mul_reg_opr_opr
, 0},
3632 {"modu.pb", 2, 0x38, mul_reg_opr_opr
, 0},
3633 {"modu.pw", 2, 0x38, mul_reg_opr_opr
, 0},
3634 {"modu.pp", 2, 0x38, mul_reg_opr_opr
, 0},
3635 {"modu.pl", 2, 0x38, mul_reg_opr_opr
, 0},
3637 {"modu.lb", 2, 0x38, mul_reg_opr_opr
, 0},
3638 {"modu.lw", 2, 0x38, mul_reg_opr_opr
, 0},
3639 {"modu.lp", 2, 0x38, mul_reg_opr_opr
, 0},
3640 {"modu.ll", 2, 0x38, mul_reg_opr_opr
, 0}
3644 /* Gas line assembler entry point. */
3646 /* This is the main entry point for the machine-dependent assembler. str
3647 points to a machine-dependent instruction. This function is supposed to
3648 emit the frags/bytes it assembles to. */
3650 md_assemble (char *str
)
3657 fail_line_pointer
= NULL
;
3659 /* Find the opcode end and get the opcode in 'name'. The opcode is forced
3660 lower case (the opcode table only has lower case op-codes). */
3661 for (op_start
= op_end
= str
;
3662 *op_end
&& !is_end_of_line
[(int)*op_end
] && *op_end
!= ' ';
3665 name
[nlen
] = TOLOWER (op_start
[nlen
]);
3667 gas_assert (nlen
< sizeof (name
) - 1);
3673 as_bad (_("No instruction or missing opcode."));
3677 input_line_pointer
= skip_whites (op_end
);
3680 for (i
= 0; i
< sizeof (opcodes
) / sizeof (opcodes
[0]); ++i
)
3682 const struct instruction
*opc
= opcodes
+ i
;
3683 if (0 == strcmp (name
, opc
->name
))
3685 if (opc
->parse_operands (opc
))
3691 as_bad (_("Invalid instruction: \"%s\""), str
);
3692 as_bad (_("First invalid token: \"%s\""), fail_line_pointer
);
3693 while (*input_line_pointer
++)
3701 /* Relocation, relaxation and frag conversions. */
3703 /* PC-relative offsets are relative to the start of the
3704 next instruction. That is, the address of the offset, plus its
3705 size, since the offset is always the last part of the insn. */
3707 md_pcrel_from (fixS
*fixP
)
3709 long ret
= fixP
->fx_size
+ fixP
->fx_frag
->fr_address
;
3710 if (fixP
->fx_addsy
&& S_IS_DEFINED (fixP
->fx_addsy
))
3711 ret
+= fixP
->fx_where
;
3717 /* We need a port-specific relaxation function to cope with sym2 - sym1
3718 relative expressions with both symbols in the same segment (but not
3719 necessarily in the same frag as this insn), for example:
3720 ldab sym2-(sym1-2),pc
3722 The offset can be 5, 9 or 16 bits long. */
3725 s12z_relax_frag (segT seg ATTRIBUTE_UNUSED
, fragS
*fragP ATTRIBUTE_UNUSED
,
3726 long stretch ATTRIBUTE_UNUSED
)
3732 md_convert_frag (bfd
*abfd ATTRIBUTE_UNUSED
, asection
*sec ATTRIBUTE_UNUSED
,
3733 fragS
*fragP ATTRIBUTE_UNUSED
)
3737 /* On an ELF system, we can't relax a weak symbol. The weak symbol
3738 can be overridden at final link time by a non weak symbol. We can
3739 relax externally visible symbol because there is no shared library
3740 and such symbol can't be overridden (unless they are weak). */
3742 /* Force truly undefined symbols to their maximum size, and generally set up
3743 the frag list to be relaxed. */
3745 md_estimate_size_before_relax (fragS
*fragP ATTRIBUTE_UNUSED
, asection
*segment ATTRIBUTE_UNUSED
)
3751 /* If while processing a fixup, a reloc really needs to be created
3752 then it is done here. */
3754 tc_gen_reloc (asection
*section
, fixS
*fixp
)
3756 arelent
*reloc
= XNEW (arelent
);
3757 reloc
->sym_ptr_ptr
= XNEW (asymbol
*);
3758 *reloc
->sym_ptr_ptr
= symbol_get_bfdsym (fixp
->fx_addsy
);
3759 reloc
->address
= fixp
->fx_frag
->fr_address
+ fixp
->fx_where
;
3760 reloc
->howto
= bfd_reloc_type_lookup (stdoutput
, fixp
->fx_r_type
);
3761 if (reloc
->howto
== (reloc_howto_type
*) NULL
)
3763 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
3764 _("Relocation %d is not supported by object file format."),
3765 (int) fixp
->fx_r_type
);
3769 if (0 == (section
->flags
& SEC_CODE
))
3770 reloc
->addend
= fixp
->fx_offset
;
3772 reloc
->addend
= fixp
->fx_addnumber
;
3777 /* See whether we need to force a relocation into the output file. */
3779 tc_s12z_force_relocation (fixS
*fixP
)
3781 return generic_force_reloc (fixP
);
3784 /* Here we decide which fixups can be adjusted to make them relative
3785 to the beginning of the section instead of the symbol. Basically
3786 we need to make sure that the linker relaxation is done
3787 correctly, so in some cases we force the original symbol to be
3790 tc_s12z_fix_adjustable (fixS
*fixP ATTRIBUTE_UNUSED
)
3796 md_apply_fix (fixS
*fixP
, valueT
*valP
, segT seg ATTRIBUTE_UNUSED
)
3800 if (fixP
->fx_addsy
== (symbolS
*) NULL
)
3803 /* We don't actually support subtracting a symbol. */
3804 if (fixP
->fx_subsy
!= (symbolS
*) NULL
)
3805 as_bad_where (fixP
->fx_file
, fixP
->fx_line
, _("Expression too complex."));
3808 Patch the instruction with the resolved operand. Elf relocation
3809 info will also be generated to take care of linker/loader fixups.
3811 char *where
= fixP
->fx_frag
->fr_literal
+ fixP
->fx_where
;
3813 switch (fixP
->fx_r_type
)
3816 ((bfd_byte
*) where
)[0] = (bfd_byte
) value
;
3819 bfd_putb16 ((bfd_vma
) value
, (unsigned char *) where
);
3822 bfd_putb24 ((bfd_vma
) value
, (unsigned char *) where
);
3825 bfd_putb32 ((bfd_vma
) value
, (unsigned char *) where
);
3827 case BFD_RELOC_16_PCREL
:
3828 if (value
< -0x8000 || value
> 0x7FFF)
3829 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
3830 _("Value out of 16-bit range."));
3832 bfd_putb16 ((bfd_vma
) value
| 0x8000, (unsigned char *) where
);
3836 as_fatal (_("Line %d: unknown relocation type: 0x%x."),
3837 fixP
->fx_line
, fixP
->fx_r_type
);
3841 /* Set the ELF specific flags. */
3843 s12z_elf_final_processing (void)