1 /* tc-s12z.c -- Assembler code for the Freescale S12Z
2 Copyright (C) 2018-2019 Free Software Foundation, Inc.
4 This file is part of GAS, the GNU Assembler.
6 GAS is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3, or (at your option)
11 GAS is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GAS; see the file COPYING. If not, write to
18 the Free Software Foundation, 51 Franklin Street - Fifth Floor,
19 Boston, MA 02110-1301, USA. */
22 #include "safe-ctype.h"
24 #include "dwarf2dbg.h"
25 #include "opcode/s12z.h"
30 const char comment_chars
[] = ";";
32 const char line_comment_chars
[] = "#*";
33 const char line_separator_chars
[] = "";
35 const char EXP_CHARS
[] = "eE";
36 const char FLT_CHARS
[] = "dD";
38 static char *fail_line_pointer
;
41 /* Options and initialization. */
43 const char *md_shortopts
= "Sm:";
45 struct option md_longopts
[] =
49 size_t md_longopts_size
= sizeof (md_longopts
);
52 relax_typeS md_relax_table
[] =
57 /* This table describes all the machine specific pseudo-ops the assembler
58 has to support. The fields are:
59 pseudo-op name without dot
60 function to call to execute this pseudo-op
61 Integer arg to pass to the function. */
62 const pseudo_typeS md_pseudo_table
[] =
68 /* Get the target cpu for the assembler. */
70 s12z_arch_format (void)
87 /* Listing header selected according to cpu. */
89 s12z_listing_header (void)
95 md_show_usage (FILE *stream ATTRIBUTE_UNUSED
)
100 s12z_print_statistics (FILE *file ATTRIBUTE_UNUSED
)
105 md_parse_option (int c ATTRIBUTE_UNUSED
, const char *arg ATTRIBUTE_UNUSED
)
111 md_undefined_symbol (char *name ATTRIBUTE_UNUSED
)
117 md_atof (int type
, char *litP
, int *sizeP
)
119 return ieee_md_atof (type
, litP
, sizeP
, TRUE
);
123 md_section_align (asection
*seg
, valueT addr
)
125 int align
= bfd_get_section_alignment (stdoutput
, seg
);
126 return ((addr
+ (1 << align
) - 1) & -(1 << align
));
135 s12z_init_after_args (void)
143 skip_whites (char *p
)
145 while (*p
== ' ' || *p
== '\t')
153 /* Start a new insn that contains at least 'size' bytes. Record the
154 line information of that insn in the dwarf2 debug sections. */
156 s12z_new_insn (int size
)
158 char *f
= frag_more (size
);
160 dwarf2_emit_insn (size
);
167 static int lex_reg_name (uint16_t which
, int *reg
);
170 lex_constant (long *v
)
173 char *p
= input_line_pointer
;
175 /* A constant may not have the same value as a register
178 if (lex_reg_name (~0, &dummy
))
180 input_line_pointer
= p
;
185 *v
= strtol (p
, &end
, 0);
186 if (errno
== 0 && end
!= p
)
188 input_line_pointer
= end
;
198 char *p
= input_line_pointer
;
202 input_line_pointer
++;
208 lex_expression (expressionS
*exp
)
210 char *ilp
= input_line_pointer
;
212 exp
->X_op
= O_absent
;
217 if (lex_reg_name (~0, &dummy
))
221 if (exp
->X_op
!= O_absent
)
225 fail_line_pointer
= input_line_pointer
;
226 input_line_pointer
= ilp
;
230 /* immediate operand */
234 char *ilp
= input_line_pointer
;
236 if (*input_line_pointer
!= '#')
239 input_line_pointer
++;
241 if (!lex_expression (&exp
))
244 if (exp
.X_op
!= O_constant
)
247 *v
= exp
.X_add_number
;
251 fail_line_pointer
= input_line_pointer
;
252 input_line_pointer
= ilp
;
256 /* Short mmediate operand */
258 lex_imm_e4 (long *val
)
260 char *ilp
= input_line_pointer
;
263 if ((*val
== -1) || (*val
> 0 && *val
<= 15))
268 fail_line_pointer
= input_line_pointer
;
269 input_line_pointer
= ilp
;
274 lex_match_string (const char *s
)
276 char *p
= input_line_pointer
;
277 while (p
!= 0 && *p
!= '\t' && *p
!= ' ' && *p
!= '\0')
282 size_t len
= p
- input_line_pointer
;
283 if (len
!= strlen (s
))
286 if (0 == strncasecmp (s
, input_line_pointer
, len
))
288 input_line_pointer
= p
;
295 /* Parse a register name.
296 WHICH is a ORwise combination of the registers which are accepted.
298 On success, REG will be filled with the index of the register which
299 was successfully scanned.
302 lex_reg_name (uint16_t which
, int *reg
)
304 char *p
= input_line_pointer
;
306 ((*p
>= 'a' && *p
<='z') || (*p
>= '0' && *p
<= '9') || (*p
>= 'A' && *p
<='Z')))
311 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 fixS
*fix
= fix_new_exp (frag_now
,
736 f
- frag_now
->fr_literal
,
741 /* Some third party tools seem to use the lower bits
742 of this addend for flags. They don't get added
743 to the final location. The purpose of these flags
744 is not known. We simply set it to zero. */
745 fix
->fx_addnumber
= 0x00;
747 for (i
= 1; i
< n_bytes
; ++i
)
748 number_to_chars_bigendian (f
++, buffer
[i
], 1);
753 /* Emit the code for a 24 bit direct address operand */
755 emit_ext24 (char *f
, long v
)
757 number_to_chars_bigendian (f
, v
, 3);
763 opr (const struct instruction
*insn
)
768 if (lex_opr (buffer
, &n_bytes
, &exp
))
770 /* Large constant direct values are more efficiently encoded as ext24 mode.
771 Otherwise a decision has to be deferred to a relax. */
772 if (exp
.X_op
== O_constant
774 && insn
->alt_opc
!= 0)
776 char *f
= s12z_new_insn (4);
778 /* I don't think there are any instances of page 2 opcodes in this case */
779 gas_assert (insn
->page
== 1);
781 number_to_chars_bigendian (f
++, insn
->alt_opc
, 1);
783 emit_ext24 (f
, exp
.X_add_number
);
787 char *f
= s12z_new_insn (n_bytes
+ 1);
788 number_to_chars_bigendian (f
++, insn
->opc
, 1);
790 emit_opr (f
, buffer
, n_bytes
, &exp
);
798 /* Parse a 15 bit offset, as an expression.
799 LONG_DISPLACEMENT will be set to true if the offset is wider than 7 bits.
802 lex_15_bit_offset (bool *long_displacement
, expressionS
*exp
)
804 char *ilp
= input_line_pointer
;
807 if (lex_offset (&val
))
809 exp
->X_op
= O_absent
;
810 exp
->X_add_number
= val
;
812 else if (lex_expression (exp
))
814 if (exp
->X_op
== O_constant
)
816 val
= exp
->X_add_number
;
820 /* If a symbol was parsed we don't know the displacement.
821 We have to assume it is long, and relax it later if possible. */
822 *long_displacement
= true;
828 exp
->X_op
= O_absent
;
832 if (val
> 0x3FFF || val
< -0x4000)
834 as_fatal (_("Offset is outside of 15 bit range"));
838 *long_displacement
= (val
> 63 || val
< -64);
843 fail_line_pointer
= input_line_pointer
;
844 input_line_pointer
= ilp
;
849 emit_15_bit_offset (char *f
, int where
, expressionS
*exp
)
852 if (exp
->X_op
!= O_absent
&& exp
->X_op
!= O_constant
)
854 exp
->X_add_number
+= where
;
855 fixS
*fix
= fix_new_exp (frag_now
,
856 f
- frag_now
->fr_literal
,
861 fix
->fx_addnumber
= where
- 2;
865 long val
= exp
->X_add_number
;
866 bool long_displacement
= (val
> 63 || val
< -64);
867 if (long_displacement
)
872 number_to_chars_bigendian (f
++, val
, long_displacement
? 2 : 1);
877 rel (const struct instruction
*insn
)
879 bool long_displacement
;
882 if (! lex_15_bit_offset (&long_displacement
, &exp
))
885 char *f
= s12z_new_insn (long_displacement
? 3 : 2);
886 number_to_chars_bigendian (f
++, insn
->opc
, 1);
887 emit_15_bit_offset (f
, 3, &exp
);
892 reg_inh (const struct instruction
*insn
)
895 if (lex_reg_name (REG_BIT_Dn
, ®
))
897 char *f
= s12z_new_insn (insn
->page
);
899 number_to_chars_bigendian (f
++, PAGE2_PREBYTE
, 1);
901 number_to_chars_bigendian (f
++, insn
->opc
+ reg
, 1);
909 /* Special case for CLR X and CLR Y */
911 clr_xy (const struct instruction
*insn ATTRIBUTE_UNUSED
)
914 if (lex_reg_name (REG_BIT_XY
, ®
))
916 char *f
= s12z_new_insn (1);
917 number_to_chars_bigendian (f
, 0x9a + reg
- REG_X
, 1);
924 /* Some instructions have a suffix like ".l", ".b", ".w" etc
925 which indicates the size of the operands. */
927 size_from_suffix (const struct instruction
*insn
, int idx
)
929 const char *dot
= strchr (insn
->name
, '.');
935 switch (dot
[1 + idx
])
950 as_fatal (_("Bad size"));
957 mul_reg_reg_reg (const struct instruction
*insn
)
959 char *ilp
= input_line_pointer
;
962 if (!lex_reg_name (REG_BIT_Dn
, &Dd
))
965 if (!lex_match (','))
969 if (!lex_reg_name (REG_BIT_Dn
, &Dj
))
972 if (!lex_match (','))
976 if (!lex_reg_name (REG_BIT_Dn
, &Dk
))
979 char *f
= s12z_new_insn (insn
->page
+ 1);
981 number_to_chars_bigendian (f
++, PAGE2_PREBYTE
, 1);
983 number_to_chars_bigendian (f
++, insn
->opc
+ Dd
, 1);
984 const char *dot
= strchrnul (insn
->name
, '.');
995 as_fatal (_("BAD MUL"));
1002 number_to_chars_bigendian (f
++, mb
, 1);
1007 fail_line_pointer
= input_line_pointer
;
1008 input_line_pointer
= ilp
;
1014 mul_reg_reg_imm (const struct instruction
*insn
)
1016 char *ilp
= input_line_pointer
;
1019 if (!lex_reg_name (REG_BIT_Dn
, &Dd
))
1022 if (!lex_match (','))
1026 if (!lex_reg_name (REG_BIT_Dn
, &Dj
))
1029 if (!lex_match (','))
1033 if (!lex_imm (&imm
))
1037 int size
= size_from_suffix (insn
, 0);
1039 char *f
= s12z_new_insn (insn
->page
+ 1 + size
);
1040 if (insn
->page
== 2)
1041 number_to_chars_bigendian (f
++, PAGE2_PREBYTE
, 1);
1043 number_to_chars_bigendian (f
++, insn
->opc
+ Dd
, 1);
1045 const char *dot
= strchrnul (insn
->name
, '.');
1055 as_fatal (_("BAD MUL"));
1062 number_to_chars_bigendian (f
++, mb
, 1);
1063 number_to_chars_bigendian (f
++, imm
, size
);
1068 fail_line_pointer
= input_line_pointer
;
1069 input_line_pointer
= ilp
;
1075 mul_reg_reg_opr (const struct instruction
*insn
)
1077 char *ilp
= input_line_pointer
;
1080 if (!lex_reg_name (REG_BIT_Dn
, &Dd
))
1083 if (!lex_match (','))
1087 if (!lex_reg_name (REG_BIT_Dn
, &Dj
))
1090 if (!lex_match (','))
1096 if (!lex_opr (buffer
, &n_bytes
, &exp
))
1099 int size
= size_from_suffix (insn
, 0);
1101 char *f
= s12z_new_insn (insn
->page
+ 1 + n_bytes
);
1102 if (insn
->page
== 2)
1103 number_to_chars_bigendian (f
++, PAGE2_PREBYTE
, 1);
1105 number_to_chars_bigendian (f
++, insn
->opc
+ Dd
, 1);
1107 const char *dot
= strchrnul (insn
->name
, '.');
1117 as_fatal (_("BAD MUL"));
1124 number_to_chars_bigendian (f
++, mb
, 1);
1126 emit_opr (f
, buffer
, n_bytes
, &exp
);
1131 fail_line_pointer
= input_line_pointer
;
1132 input_line_pointer
= ilp
;
1137 mul_reg_opr_opr (const struct instruction
*insn
)
1139 char *ilp
= input_line_pointer
;
1142 if (!lex_reg_name (REG_BIT_Dn
, &Dd
))
1145 if (!lex_match (','))
1151 if (!lex_opr (buffer1
, &n_bytes1
, &exp1
))
1154 if (!lex_match (','))
1160 if (!lex_opr (buffer2
, &n_bytes2
, &exp2
))
1163 int size1
= size_from_suffix (insn
, 0);
1164 int size2
= size_from_suffix (insn
, 1);
1166 char *f
= s12z_new_insn (insn
->page
+ 1 + n_bytes1
+ n_bytes2
);
1167 if (insn
->page
== 2)
1168 number_to_chars_bigendian (f
++, PAGE2_PREBYTE
, 1);
1170 number_to_chars_bigendian (f
++, insn
->opc
+ Dd
, 1);
1172 const char *dot
= strchrnul (insn
->name
, '.');
1182 as_fatal (_("BAD MUL"));
1186 mb
|= (size1
- 1) << 4;
1187 mb
|= (size2
- 1) << 2;
1188 number_to_chars_bigendian (f
++, mb
, 1);
1190 f
= emit_opr (f
, buffer1
, n_bytes1
, &exp1
);
1191 f
= emit_opr (f
, buffer2
, n_bytes2
, &exp2
);
1196 fail_line_pointer
= input_line_pointer
;
1197 input_line_pointer
= ilp
;
1202 #define REG_BIT_GRP0 \
1203 ((0x1U << REG_D2) | \
1204 (0x1U << REG_D3) | \
1205 (0x1U << REG_CCH) | \
1206 (0x1U << REG_CCL) | \
1207 (0x1U << REG_D0) | \
1210 #define REG_BIT_GRP1 \
1211 ((0x1U << REG_D4) | \
1212 (0x1U << REG_D5) | \
1213 (0x1U << REG_D6) | \
1214 (0x1U << REG_D7) | \
1218 static const uint8_t reg_map
[] =
1238 lex_reg_list (uint16_t grp
, uint16_t *reg_bits
)
1240 if (lex_match (','))
1243 if (!lex_reg_name (grp
, ®
))
1245 *reg_bits
|= 0x1u
<< reg
;
1246 lex_reg_list (grp
, reg_bits
);
1254 psh_pull (const struct instruction
*insn
)
1257 (0 == strcmp ("pul", insn
->name
)) ? 0x80: 0x00;
1259 if (lex_match_string ("all16b"))
1263 else if (lex_match_string ("all"))
1270 if (!lex_reg_name (REG_BIT_GRP1
| REG_BIT_GRP0
, ®1
))
1272 uint16_t admitted_group
= 0;
1274 if ((0x1U
<< reg1
) & REG_BIT_GRP1
)
1275 admitted_group
= REG_BIT_GRP1
;
1276 else if ((0x1U
<< reg1
) & REG_BIT_GRP0
)
1277 admitted_group
= REG_BIT_GRP0
;
1279 uint16_t reg_bits
= 0x1 << reg1
;
1280 if (!lex_reg_list (admitted_group
, ®_bits
))
1283 if (reg_bits
& REG_BIT_GRP1
)
1287 for (i
= 0; i
< 16; ++i
)
1289 if (reg_bits
& (0x1u
<< i
))
1294 char *f
= s12z_new_insn (2);
1295 number_to_chars_bigendian (f
++, insn
->opc
, 1);
1296 number_to_chars_bigendian (f
++, pb
, 1);
1300 fail_line_pointer
= input_line_pointer
;
1306 tfr (const struct instruction
*insn
)
1309 if (!lex_reg_name (~0, ®1
))
1312 if (!lex_match (','))
1316 if (!lex_reg_name (~0, ®2
))
1319 if ( ((0 == strcasecmp ("sex", insn
->name
))
1320 || (0 == strcasecmp ("zex", insn
->name
)))
1321 && (registers
[reg2
].bytes
<= registers
[reg1
].bytes
))
1322 as_warn (_("Source register for %s is no larger than 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 {"bhs", 1, 0x24, rel
, 0}, /* Alias for bcc */
3146 {"bcs", 1, 0x25, rel
, 0},
3147 {"blo", 1, 0x25, rel
, 0}, /* Alias for bcs */
3148 {"bne", 1, 0x26, rel
, 0},
3149 {"beq", 1, 0x27, rel
, 0},
3150 {"bvc", 1, 0x28, rel
, 0},
3151 {"bvs", 1, 0x29, rel
, 0},
3152 {"bpl", 1, 0x2a, rel
, 0},
3153 {"bmi", 1, 0x2b, rel
, 0},
3154 {"bge", 1, 0x2c, rel
, 0},
3155 {"blt", 1, 0x2d, rel
, 0},
3156 {"bgt", 1, 0x2e, rel
, 0},
3157 {"ble", 1, 0x2f, rel
, 0},
3159 {"inc", 1, 0x30, reg_inh
, 0},
3160 {"clr", 1, 0x38, reg_inh
, 0},
3161 {"dec", 1, 0x40, reg_inh
, 0},
3163 {"muls", 1, 0x48, mul_reg_reg_reg
, 0},
3164 {"mulu", 1, 0x48, mul_reg_reg_reg
, 0},
3166 {"muls.b", 1, 0x48, mul_reg_reg_opr
, 0},
3167 {"muls.w", 1, 0x48, mul_reg_reg_opr
, 0},
3168 {"muls.l", 1, 0x48, mul_reg_reg_opr
, 0},
3170 {"mulu.b", 1, 0x48, mul_reg_reg_opr
, 0},
3171 {"mulu.w", 1, 0x48, mul_reg_reg_opr
, 0},
3172 {"mulu.l", 1, 0x48, mul_reg_reg_opr
, 0},
3174 {"muls.b", 1, 0x48, mul_reg_reg_imm
, 0},
3175 {"muls.w", 1, 0x48, mul_reg_reg_imm
, 0},
3176 {"muls.l", 1, 0x48, mul_reg_reg_imm
, 0},
3178 {"mulu.b", 1, 0x48, mul_reg_reg_imm
, 0},
3179 {"mulu.w", 1, 0x48, mul_reg_reg_imm
, 0},
3180 {"mulu.l", 1, 0x48, mul_reg_reg_imm
, 0},
3182 {"muls.bb", 1, 0x48, mul_reg_opr_opr
, 0},
3183 {"muls.bw", 1, 0x48, mul_reg_opr_opr
, 0},
3184 {"muls.bp", 1, 0x48, mul_reg_opr_opr
, 0},
3185 {"muls.bl", 1, 0x48, mul_reg_opr_opr
, 0},
3187 {"muls.wb", 1, 0x48, mul_reg_opr_opr
, 0},
3188 {"muls.ww", 1, 0x48, mul_reg_opr_opr
, 0},
3189 {"muls.wp", 1, 0x48, mul_reg_opr_opr
, 0},
3190 {"muls.wl", 1, 0x48, mul_reg_opr_opr
, 0},
3192 {"muls.pb", 1, 0x48, mul_reg_opr_opr
, 0},
3193 {"muls.pw", 1, 0x48, mul_reg_opr_opr
, 0},
3194 {"muls.pp", 1, 0x48, mul_reg_opr_opr
, 0},
3195 {"muls.pl", 1, 0x48, mul_reg_opr_opr
, 0},
3197 {"muls.lb", 1, 0x48, mul_reg_opr_opr
, 0},
3198 {"muls.lw", 1, 0x48, mul_reg_opr_opr
, 0},
3199 {"muls.lp", 1, 0x48, mul_reg_opr_opr
, 0},
3200 {"muls.ll", 1, 0x48, mul_reg_opr_opr
, 0},
3202 {"mulu.bb", 1, 0x48, mul_reg_opr_opr
, 0},
3203 {"mulu.bw", 1, 0x48, mul_reg_opr_opr
, 0},
3204 {"mulu.bp", 1, 0x48, mul_reg_opr_opr
, 0},
3205 {"mulu.bl", 1, 0x48, mul_reg_opr_opr
, 0},
3207 {"mulu.wb", 1, 0x48, mul_reg_opr_opr
, 0},
3208 {"mulu.ww", 1, 0x48, mul_reg_opr_opr
, 0},
3209 {"mulu.wp", 1, 0x48, mul_reg_opr_opr
, 0},
3210 {"mulu.wl", 1, 0x48, mul_reg_opr_opr
, 0},
3212 {"mulu.pb", 1, 0x48, mul_reg_opr_opr
, 0},
3213 {"mulu.pw", 1, 0x48, mul_reg_opr_opr
, 0},
3214 {"mulu.pp", 1, 0x48, mul_reg_opr_opr
, 0},
3215 {"mulu.pl", 1, 0x48, mul_reg_opr_opr
, 0},
3217 {"mulu.lb", 1, 0x48, mul_reg_opr_opr
, 0},
3218 {"mulu.lw", 1, 0x48, mul_reg_opr_opr
, 0},
3219 {"mulu.lp", 1, 0x48, mul_reg_opr_opr
, 0},
3220 {"mulu.ll", 1, 0x48, mul_reg_opr_opr
, 0},
3222 {"add", 1, 0x50, regd_imm
, 0},
3223 {"and", 1, 0x58, regd_imm
, 0},
3225 {"add", 1, 0x60, regd_opr
, 0},
3226 {"and", 1, 0x68, regd_opr
, 0},
3228 {"sub", 1, 0x70, regd_imm
, 0},
3229 {"or", 1, 0x78, regd_imm
, 0},
3231 {"sub", 1, 0x80, regd_opr
, 0},
3232 {"or", 1, 0x88, regd_opr
, 0},
3234 {"ld", 1, 0x90, regdxy_imm
, 0},
3236 {"clr", 1, 0x9a, clr_xy
, 0},
3237 {"tfr", 1, 0x9e, tfr
, 0},
3238 {"zex", 1, 0x9e, tfr
, 0},
3240 {"ld", 1, 0xa0, regdxy_opr
, 0xb0},
3242 {"jmp", 1, 0xaa, opr
, 0xba},
3243 {"jsr", 1, 0xab, opr
, 0xbb},
3245 {"exg", 1, 0xae, tfr
, 0},
3246 {"sex", 1, 0xae, tfr
, 0},
3248 {"st", 1, 0xc0, regdxy_opr
, 0xd0},
3250 {"andcc", 1, 0xce, imm8
, 0},
3251 {"orcc", 1, 0xde, imm8
, 0},
3253 {"inc.b", 1, 0x9c, opr
, 0},
3254 {"inc.w", 1, 0x9d, opr
, 0},
3255 {"inc.l", 1, 0x9f, opr
, 0},
3257 {"dec.b", 1, 0xac, opr
, 0},
3258 {"dec.w", 1, 0xad, opr
, 0},
3259 {"dec.l", 1, 0xaf, opr
, 0},
3261 {"clr.b", 1, 0xbc, opr
, 0},
3262 {"clr.w", 1, 0xbd, opr
, 0},
3263 {"clr.p", 1, 0xbe, opr
, 0},
3264 {"clr.l", 1, 0xbf, opr
, 0},
3266 {"com.b", 1, 0xcc, opr
, 0},
3267 {"com.w", 1, 0xcd, opr
, 0},
3268 {"com.l", 1, 0xcf, opr
, 0},
3270 {"neg.b", 1, 0xdc, opr
, 0},
3271 {"neg.w", 1, 0xdd, opr
, 0},
3272 {"neg.l", 1, 0xdf, opr
, 0},
3274 {"bclr", 1, 0xec, bm_regd_imm
, 0},
3275 {"bset", 1, 0xed, bm_regd_imm
, 0},
3276 {"btgl", 1, 0xee, bm_regd_imm
, 0},
3278 {"bclr", 1, 0xec, bm_regd_reg
, 0},
3279 {"bset", 1, 0xed, bm_regd_reg
, 0},
3280 {"btgl", 1, 0xee, bm_regd_reg
, 0},
3282 {"bclr.b", 1, 0xec, bm_opr_imm
, 0},
3283 {"bclr.w", 1, 0xec, bm_opr_imm
, 0},
3284 {"bclr.l", 1, 0xec, bm_opr_imm
, 0},
3286 {"bset.b", 1, 0xed, bm_opr_imm
, 0},
3287 {"bset.w", 1, 0xed, bm_opr_imm
, 0},
3288 {"bset.l", 1, 0xed, bm_opr_imm
, 0},
3290 {"btgl.b", 1, 0xee, bm_opr_imm
, 0},
3291 {"btgl.w", 1, 0xee, bm_opr_imm
, 0},
3292 {"btgl.l", 1, 0xee, bm_opr_imm
, 0},
3294 {"bclr.b", 1, 0xec, bm_opr_reg
, 0},
3295 {"bclr.w", 1, 0xec, bm_opr_reg
, 0},
3296 {"bclr.l", 1, 0xec, bm_opr_reg
, 0},
3298 {"bset.b", 1, 0xed, bm_opr_reg
, 0},
3299 {"bset.w", 1, 0xed, bm_opr_reg
, 0},
3300 {"bset.l", 1, 0xed, bm_opr_reg
, 0},
3302 {"btgl.b", 1, 0xee, bm_opr_reg
, 0},
3303 {"btgl.w", 1, 0xee, bm_opr_reg
, 0},
3304 {"btgl.l", 1, 0xee, bm_opr_reg
, 0},
3306 {"cmp", 1, 0xe0, regdxy_imm
, 0},
3307 {"cmp", 1, 0xf0, regdxy_opr
, 0},
3309 {"cmp", 1, 0xfc, regx_regy
, 0},
3310 {"sub", 1, 0xfd, regd6_regx_regy
, 0},
3311 {"sub", 1, 0xfe, regd6_regy_regx
, 0},
3313 {"swi", 1, 0xff, no_operands
, 0},
3317 /* The -10 below is a kludge. The opcode is in fact 0x00 */
3318 {"ld", 2, -10, regs_opr
, 0},
3320 /* The -9 below is a kludge. The opcode is in fact 0x01 */
3321 {"st", 2, -9, regs_opr
, 0},
3323 /* The -8 below is a kludge. The opcode is in fact 0x02 */
3324 {"cmp", 2, -8, regs_opr
, 0},
3326 /* The -7 below is a kludge. The opcode is in fact 0x03 */
3327 {"ld", 2, -7, regs_imm
, 0},
3329 /* The -6 below is a kludge. The opcode is in fact 0x04 */
3330 {"cmp", 2, -6, regs_imm
, 0},
3332 {"bfext", 2, 0x08, bfe_reg_reg_reg
, 0},
3333 {"bfext", 2, 0x08, bfe_reg_reg_imm
, 0},
3334 {"bfext.b", 2, 0x08, bfe_reg_opr_reg
, 0},
3335 {"bfext.w", 2, 0x08, bfe_reg_opr_reg
, 0},
3336 {"bfext.p", 2, 0x08, bfe_reg_opr_reg
, 0},
3337 {"bfext.l", 2, 0x08, bfe_reg_opr_reg
, 0},
3338 {"bfext.b", 2, 0x08, bfe_opr_reg_reg
, 0},
3339 {"bfext.w", 2, 0x08, bfe_opr_reg_reg
, 0},
3340 {"bfext.p", 2, 0x08, bfe_opr_reg_reg
, 0},
3341 {"bfext.l", 2, 0x08, bfe_opr_reg_reg
, 0},
3342 {"bfext.b", 2, 0x08, bfe_reg_opr_imm
, 0},
3343 {"bfext.w", 2, 0x08, bfe_reg_opr_imm
, 0},
3344 {"bfext.p", 2, 0x08, bfe_reg_opr_imm
, 0},
3345 {"bfext.l", 2, 0x08, bfe_reg_opr_imm
, 0},
3346 {"bfext.b", 2, 0x08, bfe_opr_reg_imm
, 0},
3347 {"bfext.w", 2, 0x08, bfe_opr_reg_imm
, 0},
3348 {"bfext.p", 2, 0x08, bfe_opr_reg_imm
, 0},
3349 {"bfext.l", 2, 0x08, bfe_opr_reg_imm
, 0},
3352 {"bfins", 2, 0x08, bfi_reg_reg_reg
, 0},
3353 {"bfins", 2, 0x08, bfi_reg_reg_imm
, 0},
3354 {"bfins.b", 2, 0x08, bfi_reg_opr_reg
, 0},
3355 {"bfins.w", 2, 0x08, bfi_reg_opr_reg
, 0},
3356 {"bfins.p", 2, 0x08, bfi_reg_opr_reg
, 0},
3357 {"bfins.l", 2, 0x08, bfi_reg_opr_reg
, 0},
3358 {"bfins.b", 2, 0x08, bfi_opr_reg_reg
, 0},
3359 {"bfins.w", 2, 0x08, bfi_opr_reg_reg
, 0},
3360 {"bfins.p", 2, 0x08, bfi_opr_reg_reg
, 0},
3361 {"bfins.l", 2, 0x08, bfi_opr_reg_reg
, 0},
3362 {"bfins.b", 2, 0x08, bfi_reg_opr_imm
, 0},
3363 {"bfins.w", 2, 0x08, bfi_reg_opr_imm
, 0},
3364 {"bfins.p", 2, 0x08, bfi_reg_opr_imm
, 0},
3365 {"bfins.l", 2, 0x08, bfi_reg_opr_imm
, 0},
3366 {"bfins.b", 2, 0x08, bfi_opr_reg_imm
, 0},
3367 {"bfins.w", 2, 0x08, bfi_opr_reg_imm
, 0},
3368 {"bfins.p", 2, 0x08, bfi_opr_reg_imm
, 0},
3369 {"bfins.l", 2, 0x08, bfi_opr_reg_imm
, 0},
3372 {"minu", 2, 0x10, regd_opr
, 0},
3373 {"maxu", 2, 0x18, regd_opr
, 0},
3374 {"mins", 2, 0x20, regd_opr
, 0},
3375 {"maxs", 2, 0x28, regd_opr
, 0},
3377 {"clb", 2, 0x91, tfr
, 0},
3379 {"trap", 2, 0x00, trap_imm
, 0},
3380 {"abs", 2, 0x40, reg_inh
, 0},
3381 {"sat", 2, 0xa0, reg_inh
, 0},
3383 {"rti", 2, 0x90, no_operands
, 0},
3384 {"stop", 2, 0x05, no_operands
, 0},
3385 {"wai", 2, 0x06, no_operands
, 0},
3386 {"sys", 2, 0x07, no_operands
, 0},
3388 {"bit", 2, 0x58, regd_imm
, 0},
3389 {"bit", 2, 0x68, regd_opr
, 0},
3391 {"adc", 2, 0x50, regd_imm
, 0},
3392 {"adc", 2, 0x60, regd_opr
, 0},
3394 {"sbc", 2, 0x70, regd_imm
, 0},
3395 {"eor", 2, 0x78, regd_imm
, 0},
3397 {"sbc", 2, 0x80, regd_opr
, 0},
3398 {"eor", 2, 0x88, regd_opr
, 0},
3400 {"divs", 2, 0x30, mul_reg_reg_reg
, 0},
3401 {"divu", 2, 0x30, mul_reg_reg_reg
, 0},
3403 {"divs.b", 2, 0x30, mul_reg_reg_opr
, 0},
3404 {"divs.w", 2, 0x30, mul_reg_reg_opr
, 0},
3405 {"divs.l", 2, 0x30, mul_reg_reg_opr
, 0},
3407 {"divu.b", 2, 0x30, mul_reg_reg_opr
, 0},
3408 {"divu.w", 2, 0x30, mul_reg_reg_opr
, 0},
3409 {"divu.l", 2, 0x30, mul_reg_reg_opr
, 0},
3411 {"divs.b", 2, 0x30, mul_reg_reg_imm
, 0},
3412 {"divs.w", 2, 0x30, mul_reg_reg_imm
, 0},
3413 {"divs.l", 2, 0x30, mul_reg_reg_imm
, 0},
3415 {"divu.b", 2, 0x30, mul_reg_reg_imm
, 0},
3416 {"divu.w", 2, 0x30, mul_reg_reg_imm
, 0},
3417 {"divu.l", 2, 0x30, mul_reg_reg_imm
, 0},
3419 {"divs.bb", 2, 0x30, mul_reg_opr_opr
, 0},
3420 {"divs.bw", 2, 0x30, mul_reg_opr_opr
, 0},
3421 {"divs.bp", 2, 0x30, mul_reg_opr_opr
, 0},
3422 {"divs.bl", 2, 0x30, mul_reg_opr_opr
, 0},
3424 {"divs.wb", 2, 0x30, mul_reg_opr_opr
, 0},
3425 {"divs.ww", 2, 0x30, mul_reg_opr_opr
, 0},
3426 {"divs.wp", 2, 0x30, mul_reg_opr_opr
, 0},
3427 {"divs.wl", 2, 0x30, mul_reg_opr_opr
, 0},
3429 {"divs.pb", 2, 0x30, mul_reg_opr_opr
, 0},
3430 {"divs.pw", 2, 0x30, mul_reg_opr_opr
, 0},
3431 {"divs.pp", 2, 0x30, mul_reg_opr_opr
, 0},
3432 {"divs.pl", 2, 0x30, mul_reg_opr_opr
, 0},
3434 {"divs.lb", 2, 0x30, mul_reg_opr_opr
, 0},
3435 {"divs.lw", 2, 0x30, mul_reg_opr_opr
, 0},
3436 {"divs.lp", 2, 0x30, mul_reg_opr_opr
, 0},
3437 {"divs.ll", 2, 0x30, mul_reg_opr_opr
, 0},
3439 {"divu.bb", 2, 0x30, mul_reg_opr_opr
, 0},
3440 {"divu.bw", 2, 0x30, mul_reg_opr_opr
, 0},
3441 {"divu.bp", 2, 0x30, mul_reg_opr_opr
, 0},
3442 {"divu.bl", 2, 0x30, mul_reg_opr_opr
, 0},
3444 {"divu.wb", 2, 0x30, mul_reg_opr_opr
, 0},
3445 {"divu.ww", 2, 0x30, mul_reg_opr_opr
, 0},
3446 {"divu.wp", 2, 0x30, mul_reg_opr_opr
, 0},
3447 {"divu.wl", 2, 0x30, mul_reg_opr_opr
, 0},
3449 {"divu.pb", 2, 0x30, mul_reg_opr_opr
, 0},
3450 {"divu.pw", 2, 0x30, mul_reg_opr_opr
, 0},
3451 {"divu.pp", 2, 0x30, mul_reg_opr_opr
, 0},
3452 {"divu.pl", 2, 0x30, mul_reg_opr_opr
, 0},
3454 {"divu.lb", 2, 0x30, mul_reg_opr_opr
, 0},
3455 {"divu.lw", 2, 0x30, mul_reg_opr_opr
, 0},
3456 {"divu.lp", 2, 0x30, mul_reg_opr_opr
, 0},
3457 {"divu.ll", 2, 0x30, mul_reg_opr_opr
, 0},
3461 {"qmuls", 2, 0xb0, mul_reg_reg_reg
, 0},
3462 {"qmulu", 2, 0xb0, mul_reg_reg_reg
, 0},
3464 {"qmuls.b", 2, 0xb0, mul_reg_reg_opr
, 0},
3465 {"qmuls.w", 2, 0xb0, mul_reg_reg_opr
, 0},
3466 {"qmuls.l", 2, 0xb0, mul_reg_reg_opr
, 0},
3468 {"qmulu.b", 2, 0xb0, mul_reg_reg_opr
, 0},
3469 {"qmulu.w", 2, 0xb0, mul_reg_reg_opr
, 0},
3470 {"qmulu.l", 2, 0xb0, mul_reg_reg_opr
, 0},
3472 {"qmuls.b", 2, 0xb0, mul_reg_reg_imm
, 0},
3473 {"qmuls.w", 2, 0xb0, mul_reg_reg_imm
, 0},
3474 {"qmuls.l", 2, 0xb0, mul_reg_reg_imm
, 0},
3476 {"qmulu.b", 2, 0xb0, mul_reg_reg_imm
, 0},
3477 {"qmulu.w", 2, 0xb0, mul_reg_reg_imm
, 0},
3478 {"qmulu.l", 2, 0xb0, mul_reg_reg_imm
, 0},
3480 {"qmuls.bb", 2, 0xb0, mul_reg_opr_opr
, 0},
3481 {"qmuls.bw", 2, 0xb0, mul_reg_opr_opr
, 0},
3482 {"qmuls.bp", 2, 0xb0, mul_reg_opr_opr
, 0},
3483 {"qmuls.bl", 2, 0xb0, mul_reg_opr_opr
, 0},
3485 {"qmuls.wb", 2, 0xb0, mul_reg_opr_opr
, 0},
3486 {"qmuls.ww", 2, 0xb0, mul_reg_opr_opr
, 0},
3487 {"qmuls.wp", 2, 0xb0, mul_reg_opr_opr
, 0},
3488 {"qmuls.wl", 2, 0xb0, mul_reg_opr_opr
, 0},
3490 {"qmuls.pb", 2, 0xb0, mul_reg_opr_opr
, 0},
3491 {"qmuls.pw", 2, 0xb0, mul_reg_opr_opr
, 0},
3492 {"qmuls.pp", 2, 0xb0, mul_reg_opr_opr
, 0},
3493 {"qmuls.pl", 2, 0xb0, mul_reg_opr_opr
, 0},
3495 {"qmuls.lb", 2, 0xb0, mul_reg_opr_opr
, 0},
3496 {"qmuls.lw", 2, 0xb0, mul_reg_opr_opr
, 0},
3497 {"qmuls.lp", 2, 0xb0, mul_reg_opr_opr
, 0},
3498 {"qmuls.ll", 2, 0xb0, mul_reg_opr_opr
, 0},
3500 {"qmulu.bb", 2, 0xb0, mul_reg_opr_opr
, 0},
3501 {"qmulu.bw", 2, 0xb0, mul_reg_opr_opr
, 0},
3502 {"qmulu.bp", 2, 0xb0, mul_reg_opr_opr
, 0},
3503 {"qmulu.bl", 2, 0xb0, mul_reg_opr_opr
, 0},
3505 {"qmulu.wb", 2, 0xb0, mul_reg_opr_opr
, 0},
3506 {"qmulu.ww", 2, 0xb0, mul_reg_opr_opr
, 0},
3507 {"qmulu.wp", 2, 0xb0, mul_reg_opr_opr
, 0},
3508 {"qmulu.wl", 2, 0xb0, mul_reg_opr_opr
, 0},
3510 {"qmulu.pb", 2, 0xb0, mul_reg_opr_opr
, 0},
3511 {"qmulu.pw", 2, 0xb0, mul_reg_opr_opr
, 0},
3512 {"qmulu.pp", 2, 0xb0, mul_reg_opr_opr
, 0},
3513 {"qmulu.pl", 2, 0xb0, mul_reg_opr_opr
, 0},
3515 {"qmulu.lb", 2, 0xb0, mul_reg_opr_opr
, 0},
3516 {"qmulu.lw", 2, 0xb0, mul_reg_opr_opr
, 0},
3517 {"qmulu.lp", 2, 0xb0, mul_reg_opr_opr
, 0},
3518 {"qmulu.ll", 2, 0xb0, mul_reg_opr_opr
, 0},
3523 {"macs", 2, 0x48, mul_reg_reg_reg
, 0},
3524 {"macu", 2, 0x48, mul_reg_reg_reg
, 0},
3526 {"macs.b", 2, 0x48, mul_reg_reg_opr
, 0},
3527 {"macs.w", 2, 0x48, mul_reg_reg_opr
, 0},
3528 {"macs.l", 2, 0x48, mul_reg_reg_opr
, 0},
3530 {"macu.b", 2, 0x48, mul_reg_reg_opr
, 0},
3531 {"macu.w", 2, 0x48, mul_reg_reg_opr
, 0},
3532 {"macu.l", 2, 0x48, mul_reg_reg_opr
, 0},
3534 {"macs.b", 2, 0x48, mul_reg_reg_imm
, 0},
3535 {"macs.w", 2, 0x48, mul_reg_reg_imm
, 0},
3536 {"macs.l", 2, 0x48, mul_reg_reg_imm
, 0},
3538 {"macu.b", 2, 0x48, mul_reg_reg_imm
, 0},
3539 {"macu.w", 2, 0x48, mul_reg_reg_imm
, 0},
3540 {"macu.l", 2, 0x48, mul_reg_reg_imm
, 0},
3542 {"macs.bb", 2, 0x48, mul_reg_opr_opr
, 0},
3543 {"macs.bw", 2, 0x48, mul_reg_opr_opr
, 0},
3544 {"macs.bp", 2, 0x48, mul_reg_opr_opr
, 0},
3545 {"macs.bl", 2, 0x48, mul_reg_opr_opr
, 0},
3547 {"macs.wb", 2, 0x48, mul_reg_opr_opr
, 0},
3548 {"macs.ww", 2, 0x48, mul_reg_opr_opr
, 0},
3549 {"macs.wp", 2, 0x48, mul_reg_opr_opr
, 0},
3550 {"macs.wl", 2, 0x48, mul_reg_opr_opr
, 0},
3552 {"macs.pb", 2, 0x48, mul_reg_opr_opr
, 0},
3553 {"macs.pw", 2, 0x48, mul_reg_opr_opr
, 0},
3554 {"macs.pp", 2, 0x48, mul_reg_opr_opr
, 0},
3555 {"macs.pl", 2, 0x48, mul_reg_opr_opr
, 0},
3557 {"macs.lb", 2, 0x48, mul_reg_opr_opr
, 0},
3558 {"macs.lw", 2, 0x48, mul_reg_opr_opr
, 0},
3559 {"macs.lp", 2, 0x48, mul_reg_opr_opr
, 0},
3560 {"macs.ll", 2, 0x48, mul_reg_opr_opr
, 0},
3562 {"macu.bb", 2, 0x48, mul_reg_opr_opr
, 0},
3563 {"macu.bw", 2, 0x48, mul_reg_opr_opr
, 0},
3564 {"macu.bp", 2, 0x48, mul_reg_opr_opr
, 0},
3565 {"macu.bl", 2, 0x48, mul_reg_opr_opr
, 0},
3567 {"macu.wb", 2, 0x48, mul_reg_opr_opr
, 0},
3568 {"macu.ww", 2, 0x48, mul_reg_opr_opr
, 0},
3569 {"macu.wp", 2, 0x48, mul_reg_opr_opr
, 0},
3570 {"macu.wl", 2, 0x48, mul_reg_opr_opr
, 0},
3572 {"macu.pb", 2, 0x48, mul_reg_opr_opr
, 0},
3573 {"macu.pw", 2, 0x48, mul_reg_opr_opr
, 0},
3574 {"macu.pp", 2, 0x48, mul_reg_opr_opr
, 0},
3575 {"macu.pl", 2, 0x48, mul_reg_opr_opr
, 0},
3577 {"macu.lb", 2, 0x48, mul_reg_opr_opr
, 0},
3578 {"macu.lw", 2, 0x48, mul_reg_opr_opr
, 0},
3579 {"macu.lp", 2, 0x48, mul_reg_opr_opr
, 0},
3580 {"macu.ll", 2, 0x48, mul_reg_opr_opr
, 0},
3585 {"mods", 2, 0x38, mul_reg_reg_reg
, 0},
3586 {"modu", 2, 0x38, mul_reg_reg_reg
, 0},
3588 {"mods.b", 2, 0x38, mul_reg_reg_opr
, 0},
3589 {"mods.w", 2, 0x38, mul_reg_reg_opr
, 0},
3590 {"mods.l", 2, 0x38, mul_reg_reg_opr
, 0},
3592 {"modu.b", 2, 0x38, mul_reg_reg_opr
, 0},
3593 {"modu.w", 2, 0x38, mul_reg_reg_opr
, 0},
3594 {"modu.l", 2, 0x38, mul_reg_reg_opr
, 0},
3596 {"mods.b", 2, 0x38, mul_reg_reg_imm
, 0},
3597 {"mods.w", 2, 0x38, mul_reg_reg_imm
, 0},
3598 {"mods.l", 2, 0x38, mul_reg_reg_imm
, 0},
3600 {"modu.b", 2, 0x38, mul_reg_reg_imm
, 0},
3601 {"modu.w", 2, 0x38, mul_reg_reg_imm
, 0},
3602 {"modu.l", 2, 0x38, mul_reg_reg_imm
, 0},
3604 {"mods.bb", 2, 0x38, mul_reg_opr_opr
, 0},
3605 {"mods.bw", 2, 0x38, mul_reg_opr_opr
, 0},
3606 {"mods.bp", 2, 0x38, mul_reg_opr_opr
, 0},
3607 {"mods.bl", 2, 0x38, mul_reg_opr_opr
, 0},
3609 {"mods.wb", 2, 0x38, mul_reg_opr_opr
, 0},
3610 {"mods.ww", 2, 0x38, mul_reg_opr_opr
, 0},
3611 {"mods.wp", 2, 0x38, mul_reg_opr_opr
, 0},
3612 {"mods.wl", 2, 0x38, mul_reg_opr_opr
, 0},
3614 {"mods.pb", 2, 0x38, mul_reg_opr_opr
, 0},
3615 {"mods.pw", 2, 0x38, mul_reg_opr_opr
, 0},
3616 {"mods.pp", 2, 0x38, mul_reg_opr_opr
, 0},
3617 {"mods.pl", 2, 0x38, mul_reg_opr_opr
, 0},
3619 {"mods.lb", 2, 0x38, mul_reg_opr_opr
, 0},
3620 {"mods.lw", 2, 0x38, mul_reg_opr_opr
, 0},
3621 {"mods.lp", 2, 0x38, mul_reg_opr_opr
, 0},
3622 {"mods.ll", 2, 0x38, mul_reg_opr_opr
, 0},
3624 {"modu.bb", 2, 0x38, mul_reg_opr_opr
, 0},
3625 {"modu.bw", 2, 0x38, mul_reg_opr_opr
, 0},
3626 {"modu.bp", 2, 0x38, mul_reg_opr_opr
, 0},
3627 {"modu.bl", 2, 0x38, mul_reg_opr_opr
, 0},
3629 {"modu.wb", 2, 0x38, mul_reg_opr_opr
, 0},
3630 {"modu.ww", 2, 0x38, mul_reg_opr_opr
, 0},
3631 {"modu.wp", 2, 0x38, mul_reg_opr_opr
, 0},
3632 {"modu.wl", 2, 0x38, mul_reg_opr_opr
, 0},
3634 {"modu.pb", 2, 0x38, mul_reg_opr_opr
, 0},
3635 {"modu.pw", 2, 0x38, mul_reg_opr_opr
, 0},
3636 {"modu.pp", 2, 0x38, mul_reg_opr_opr
, 0},
3637 {"modu.pl", 2, 0x38, mul_reg_opr_opr
, 0},
3639 {"modu.lb", 2, 0x38, mul_reg_opr_opr
, 0},
3640 {"modu.lw", 2, 0x38, mul_reg_opr_opr
, 0},
3641 {"modu.lp", 2, 0x38, mul_reg_opr_opr
, 0},
3642 {"modu.ll", 2, 0x38, mul_reg_opr_opr
, 0}
3646 /* Gas line assembler entry point. */
3648 /* This is the main entry point for the machine-dependent assembler. str
3649 points to a machine-dependent instruction. This function is supposed to
3650 emit the frags/bytes it assembles to. */
3652 md_assemble (char *str
)
3659 fail_line_pointer
= NULL
;
3661 /* Find the opcode end and get the opcode in 'name'. The opcode is forced
3662 lower case (the opcode table only has lower case op-codes). */
3663 for (op_start
= op_end
= str
;
3664 *op_end
&& !is_end_of_line
[(int)*op_end
] && *op_end
!= ' ';
3667 name
[nlen
] = TOLOWER (op_start
[nlen
]);
3669 gas_assert (nlen
< sizeof (name
) - 1);
3675 as_bad (_("No instruction or missing opcode."));
3679 input_line_pointer
= skip_whites (op_end
);
3682 for (i
= 0; i
< sizeof (opcodes
) / sizeof (opcodes
[0]); ++i
)
3684 const struct instruction
*opc
= opcodes
+ i
;
3685 if (0 == strcmp (name
, opc
->name
))
3687 if (opc
->parse_operands (opc
))
3693 as_bad (_("Invalid instruction: \"%s\""), str
);
3694 as_bad (_("First invalid token: \"%s\""), fail_line_pointer
);
3695 while (*input_line_pointer
++)
3703 /* Relocation, relaxation and frag conversions. */
3705 /* PC-relative offsets are relative to the start of the
3706 next instruction. That is, the address of the offset, plus its
3707 size, since the offset is always the last part of the insn. */
3709 md_pcrel_from (fixS
*fixP
)
3711 long ret
= fixP
->fx_size
+ fixP
->fx_frag
->fr_address
;
3712 if (fixP
->fx_addsy
&& S_IS_DEFINED (fixP
->fx_addsy
))
3713 ret
+= fixP
->fx_where
;
3719 /* We need a port-specific relaxation function to cope with sym2 - sym1
3720 relative expressions with both symbols in the same segment (but not
3721 necessarily in the same frag as this insn), for example:
3722 ldab sym2-(sym1-2),pc
3724 The offset can be 5, 9 or 16 bits long. */
3727 s12z_relax_frag (segT seg ATTRIBUTE_UNUSED
, fragS
*fragP ATTRIBUTE_UNUSED
,
3728 long stretch ATTRIBUTE_UNUSED
)
3734 md_convert_frag (bfd
*abfd ATTRIBUTE_UNUSED
, asection
*sec ATTRIBUTE_UNUSED
,
3735 fragS
*fragP ATTRIBUTE_UNUSED
)
3739 /* On an ELF system, we can't relax a weak symbol. The weak symbol
3740 can be overridden at final link time by a non weak symbol. We can
3741 relax externally visible symbol because there is no shared library
3742 and such symbol can't be overridden (unless they are weak). */
3744 /* Force truly undefined symbols to their maximum size, and generally set up
3745 the frag list to be relaxed. */
3747 md_estimate_size_before_relax (fragS
*fragP ATTRIBUTE_UNUSED
, asection
*segment ATTRIBUTE_UNUSED
)
3753 /* If while processing a fixup, a reloc really needs to be created
3754 then it is done here. */
3756 tc_gen_reloc (asection
*section
, fixS
*fixp
)
3758 arelent
*reloc
= XNEW (arelent
);
3759 reloc
->sym_ptr_ptr
= XNEW (asymbol
*);
3760 *reloc
->sym_ptr_ptr
= symbol_get_bfdsym (fixp
->fx_addsy
);
3761 reloc
->address
= fixp
->fx_frag
->fr_address
+ fixp
->fx_where
;
3762 reloc
->howto
= bfd_reloc_type_lookup (stdoutput
, fixp
->fx_r_type
);
3763 if (reloc
->howto
== (reloc_howto_type
*) NULL
)
3765 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
3766 _("Relocation %d is not supported by object file format."),
3767 (int) fixp
->fx_r_type
);
3771 if (0 == (section
->flags
& SEC_CODE
))
3772 reloc
->addend
= fixp
->fx_offset
;
3774 reloc
->addend
= fixp
->fx_addnumber
;
3779 /* See whether we need to force a relocation into the output file. */
3781 tc_s12z_force_relocation (fixS
*fixP
)
3783 return generic_force_reloc (fixP
);
3786 /* Here we decide which fixups can be adjusted to make them relative
3787 to the beginning of the section instead of the symbol. Basically
3788 we need to make sure that the linker relaxation is done
3789 correctly, so in some cases we force the original symbol to be
3792 tc_s12z_fix_adjustable (fixS
*fixP ATTRIBUTE_UNUSED
)
3798 md_apply_fix (fixS
*fixP
, valueT
*valP
, segT seg ATTRIBUTE_UNUSED
)
3802 if (fixP
->fx_addsy
== (symbolS
*) NULL
)
3805 /* We don't actually support subtracting a symbol. */
3806 if (fixP
->fx_subsy
!= (symbolS
*) NULL
)
3807 as_bad_where (fixP
->fx_file
, fixP
->fx_line
, _("Expression too complex."));
3810 Patch the instruction with the resolved operand. Elf relocation
3811 info will also be generated to take care of linker/loader fixups.
3813 char *where
= fixP
->fx_frag
->fr_literal
+ fixP
->fx_where
;
3815 switch (fixP
->fx_r_type
)
3818 ((bfd_byte
*) where
)[0] = (bfd_byte
) value
;
3821 bfd_putb16 ((bfd_vma
) value
, (unsigned char *) where
);
3824 case BFD_RELOC_S12Z_OPR
:
3825 bfd_putb24 ((bfd_vma
) value
, (unsigned char *) where
);
3828 bfd_putb32 ((bfd_vma
) value
, (unsigned char *) where
);
3830 case BFD_RELOC_16_PCREL
:
3831 if (value
< -0x8000 || value
> 0x7FFF)
3832 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
3833 _("Value out of 16-bit range."));
3835 bfd_putb16 ((bfd_vma
) value
| 0x8000, (unsigned char *) where
);
3839 as_fatal (_("Line %d: unknown relocation type: 0x%x."),
3840 fixP
->fx_line
, fixP
->fx_r_type
);
3844 /* Set the ELF specific flags. */
3846 s12z_elf_final_processing (void)