1 /* tc-mn10200.c -- Assembler code for the Matsushita 10200
2 Copyright (C) 1996, 1997, 1998, 1999 Free Software Foundation.
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 2, 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, 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
25 #include "opcode/mn10200.h"
27 /* Structure to hold information about predefined registers. */
34 /* Generic assembler global variables which must be defined by all
37 /* Characters which always start a comment. */
38 const char comment_chars
[] = "#";
40 /* Characters which start a comment at the beginning of a line. */
41 const char line_comment_chars
[] = ";#";
43 /* Characters which may be used to separate multiple commands on a
45 const char line_separator_chars
[] = ";";
47 /* Characters which are used to indicate an exponent in a floating
49 const char EXP_CHARS
[] = "eE";
51 /* Characters which mean that a number is a floating point constant,
53 const char FLT_CHARS
[] = "dD";
55 const relax_typeS md_relax_table
[] = {
58 {0x8004, -0x7ffb, 5, 2},
59 {0x800006, -0x7ffff9, 7, 0},
62 {0x8004, -0x7ffb, 6, 5},
63 {0x800006, -0x7ffff9, 8, 0},
65 {0x8004, -0x7ffb, 3, 7},
66 {0x800006, -0x7ffff9, 5, 0},
69 {0x8004, -0x7ffb, 3, 10},
70 {0x800006, -0x7ffff9, 5, 0},
74 /* Local functions. */
75 static void mn10200_insert_operand
PARAMS ((unsigned long *, unsigned long *,
76 const struct mn10200_operand
*,
77 offsetT
, char *, unsigned,
79 static unsigned long check_operand
PARAMS ((unsigned long,
80 const struct mn10200_operand
*,
82 static int reg_name_search
PARAMS ((const struct reg_name
*, int, const char *));
83 static boolean data_register_name
PARAMS ((expressionS
*expressionP
));
84 static boolean address_register_name
PARAMS ((expressionS
*expressionP
));
85 static boolean other_register_name
PARAMS ((expressionS
*expressionP
));
88 #define MAX_INSN_FIXUPS (5)
93 bfd_reloc_code_real_type reloc
;
95 struct mn10200_fixup fixups
[MAX_INSN_FIXUPS
];
98 const char *md_shortopts
= "";
99 struct option md_longopts
[] = {
100 {NULL
, no_argument
, NULL
, 0}
102 size_t md_longopts_size
= sizeof (md_longopts
);
104 /* The target specific pseudo-ops which we support. */
105 const pseudo_typeS md_pseudo_table
[] =
110 /* Opcode hash table. */
111 static struct hash_control
*mn10200_hash
;
113 /* This table is sorted. Suitable for searching by a binary search. */
114 static const struct reg_name data_registers
[] =
121 #define DATA_REG_NAME_CNT \
122 (sizeof (data_registers) / sizeof (struct reg_name))
124 static const struct reg_name address_registers
[] =
131 #define ADDRESS_REG_NAME_CNT \
132 (sizeof (address_registers) / sizeof (struct reg_name))
134 static const struct reg_name other_registers
[] =
139 #define OTHER_REG_NAME_CNT \
140 (sizeof (other_registers) / sizeof (struct reg_name))
142 /* reg_name_search does a binary search of the given register table
143 to see if "name" is a valid regiter name. Returns the register
144 number from the array on success, or -1 on failure. */
147 reg_name_search (regs
, regcount
, name
)
148 const struct reg_name
*regs
;
152 int middle
, low
, high
;
160 middle
= (low
+ high
) / 2;
161 cmp
= strcasecmp (name
, regs
[middle
].name
);
167 return regs
[middle
].value
;
173 /* Summary of register_name().
175 * in: Input_line_pointer points to 1st char of operand.
177 * out: A expressionS.
178 * The operand may have been a register: in this case, X_op == O_register,
179 * X_add_number is set to the register number, and truth is returned.
180 * Input_line_pointer->(next non-blank) char after operand, or is in
181 * its original state.
185 data_register_name (expressionP
)
186 expressionS
*expressionP
;
193 /* Find the spelling of the operand. */
194 start
= name
= input_line_pointer
;
196 c
= get_symbol_end ();
197 reg_number
= reg_name_search (data_registers
, DATA_REG_NAME_CNT
, name
);
199 /* Look to see if it's in the register table. */
202 expressionP
->X_op
= O_register
;
203 expressionP
->X_add_number
= reg_number
;
205 /* Make the rest nice. */
206 expressionP
->X_add_symbol
= NULL
;
207 expressionP
->X_op_symbol
= NULL
;
209 /* Put back the delimiting char. */
210 *input_line_pointer
= c
;
215 /* Reset the line as if we had not done anything. */
216 /* Put back the delimiting char. */
217 *input_line_pointer
= c
;
219 /* Reset input_line pointer. */
220 input_line_pointer
= start
;
225 /* Summary of register_name().
227 * in: Input_line_pointer points to 1st char of operand.
229 * out: A expressionS.
230 * The operand may have been a register: in this case, X_op == O_register,
231 * X_add_number is set to the register number, and truth is returned.
232 * Input_line_pointer->(next non-blank) char after operand, or is in
233 * its original state.
237 address_register_name (expressionP
)
238 expressionS
*expressionP
;
245 /* Find the spelling of the operand. */
246 start
= name
= input_line_pointer
;
248 c
= get_symbol_end ();
249 reg_number
= reg_name_search (address_registers
, ADDRESS_REG_NAME_CNT
, name
);
251 /* Look to see if it's in the register table. */
254 expressionP
->X_op
= O_register
;
255 expressionP
->X_add_number
= reg_number
;
257 /* Make the rest nice. */
258 expressionP
->X_add_symbol
= NULL
;
259 expressionP
->X_op_symbol
= NULL
;
261 /* Put back the delimiting char. */
262 *input_line_pointer
= c
;
267 /* Reset the line as if we had not done anything. */
268 /* Put back the delimiting char. */
269 *input_line_pointer
= c
;
271 /* Reset input_line pointer. */
272 input_line_pointer
= start
;
277 /* Summary of register_name().
279 * in: Input_line_pointer points to 1st char of operand.
281 * out: A expressionS.
282 * The operand may have been a register: in this case, X_op == O_register,
283 * X_add_number is set to the register number, and truth is returned.
284 * Input_line_pointer->(next non-blank) char after operand, or is in
285 * its original state.
289 other_register_name (expressionP
)
290 expressionS
*expressionP
;
297 /* Find the spelling of the operand. */
298 start
= name
= input_line_pointer
;
300 c
= get_symbol_end ();
301 reg_number
= reg_name_search (other_registers
, OTHER_REG_NAME_CNT
, name
);
303 /* Look to see if it's in the register table. */
306 expressionP
->X_op
= O_register
;
307 expressionP
->X_add_number
= reg_number
;
309 /* Make the rest nice. */
310 expressionP
->X_add_symbol
= NULL
;
311 expressionP
->X_op_symbol
= NULL
;
313 /* Put back the delimiting char. */
314 *input_line_pointer
= c
;
319 /* Reset the line as if we had not done anything. */
320 /* Put back the delimiting char. */
321 *input_line_pointer
= c
;
323 /* Reset input_line pointer. */
324 input_line_pointer
= start
;
330 md_show_usage (stream
)
333 fprintf (stream
, _("MN10200 options:\n\
338 md_parse_option (c
, arg
)
346 md_undefined_symbol (name
)
353 md_atof (type
, litp
, sizep
)
359 LITTLENUM_TYPE words
[4];
375 return _("bad call to md_atof");
378 t
= atof_ieee (input_line_pointer
, type
, words
);
380 input_line_pointer
= t
;
384 for (i
= prec
- 1; i
>= 0; i
--)
386 md_number_to_chars (litp
, (valueT
) words
[i
], 2);
394 md_convert_frag (abfd
, sec
, fragP
)
399 static unsigned long label_count
= 0;
402 subseg_change (sec
, 0);
403 if (fragP
->fr_subtype
== 0)
405 fix_new (fragP
, fragP
->fr_fix
+ 1, 1, fragP
->fr_symbol
,
406 fragP
->fr_offset
, 1, BFD_RELOC_8_PCREL
);
410 else if (fragP
->fr_subtype
== 1)
412 /* Reverse the condition of the first branch. */
413 int offset
= fragP
->fr_fix
;
414 int opcode
= fragP
->fr_literal
[offset
] & 0xff;
451 fragP
->fr_literal
[offset
] = opcode
;
453 /* Create a fixup for the reversed conditional branch. */
454 sprintf (buf
, ".%s_%d", FAKE_LABEL_NAME
, label_count
++);
455 fix_new (fragP
, fragP
->fr_fix
+ 1, 1,
456 symbol_new (buf
, sec
, 0, fragP
->fr_next
),
457 fragP
->fr_offset
, 1, BFD_RELOC_8_PCREL
);
459 /* Now create the unconditional branch + fixup to the
461 fragP
->fr_literal
[offset
+ 2] = 0xfc;
462 fix_new (fragP
, fragP
->fr_fix
+ 3, 2, fragP
->fr_symbol
,
463 fragP
->fr_offset
, 1, BFD_RELOC_16_PCREL
);
467 else if (fragP
->fr_subtype
== 2)
469 /* Reverse the condition of the first branch. */
470 int offset
= fragP
->fr_fix
;
471 int opcode
= fragP
->fr_literal
[offset
] & 0xff;
508 fragP
->fr_literal
[offset
] = opcode
;
510 /* Create a fixup for the reversed conditional branch. */
511 sprintf (buf
, ".%s_%d", FAKE_LABEL_NAME
, label_count
++);
512 fix_new (fragP
, fragP
->fr_fix
+ 1, 1,
513 symbol_new (buf
, sec
, 0, fragP
->fr_next
),
514 fragP
->fr_offset
, 1, BFD_RELOC_8_PCREL
);
516 /* Now create the unconditional branch + fixup to the
518 fragP
->fr_literal
[offset
+ 2] = 0xf4;
519 fragP
->fr_literal
[offset
+ 3] = 0xe0;
520 fix_new (fragP
, fragP
->fr_fix
+ 4, 4, fragP
->fr_symbol
,
521 fragP
->fr_offset
, 1, BFD_RELOC_24_PCREL
);
525 else if (fragP
->fr_subtype
== 3)
527 fix_new (fragP
, fragP
->fr_fix
+ 2, 1, fragP
->fr_symbol
,
528 fragP
->fr_offset
, 1, BFD_RELOC_8_PCREL
);
532 else if (fragP
->fr_subtype
== 4)
534 /* Reverse the condition of the first branch. */
535 int offset
= fragP
->fr_fix
;
536 int opcode
= fragP
->fr_literal
[offset
+ 1] & 0xff;
596 fragP
->fr_literal
[offset
+ 1] = opcode
;
598 /* Create a fixup for the reversed conditional branch. */
599 sprintf (buf
, ".%s_%d", FAKE_LABEL_NAME
, label_count
++);
600 fix_new (fragP
, fragP
->fr_fix
+ 2, 1,
601 symbol_new (buf
, sec
, 0, fragP
->fr_next
),
602 fragP
->fr_offset
, 1, BFD_RELOC_8_PCREL
);
604 /* Now create the unconditional branch + fixup to the
606 fragP
->fr_literal
[offset
+ 3] = 0xfc;
607 fix_new (fragP
, fragP
->fr_fix
+ 4, 2, fragP
->fr_symbol
,
608 fragP
->fr_offset
, 1, BFD_RELOC_16_PCREL
);
612 else if (fragP
->fr_subtype
== 5)
614 /* Reverse the condition of the first branch. */
615 int offset
= fragP
->fr_fix
;
616 int opcode
= fragP
->fr_literal
[offset
+ 1] & 0xff;
676 fragP
->fr_literal
[offset
+ 1] = opcode
;
678 /* Create a fixup for the reversed conditional branch. */
679 sprintf (buf
, ".%s_%d", FAKE_LABEL_NAME
, label_count
++);
680 fix_new (fragP
, fragP
->fr_fix
+ 2, 1,
681 symbol_new (buf
, sec
, 0, fragP
->fr_next
),
682 fragP
->fr_offset
, 1, BFD_RELOC_8_PCREL
);
684 /* Now create the unconditional branch + fixup to the
686 fragP
->fr_literal
[offset
+ 3] = 0xf4;
687 fragP
->fr_literal
[offset
+ 4] = 0xe0;
688 fix_new (fragP
, fragP
->fr_fix
+ 5, 4, fragP
->fr_symbol
,
689 fragP
->fr_offset
, 1, BFD_RELOC_24_PCREL
);
693 else if (fragP
->fr_subtype
== 6)
695 fix_new (fragP
, fragP
->fr_fix
+ 1, 2, fragP
->fr_symbol
,
696 fragP
->fr_offset
, 1, BFD_RELOC_16_PCREL
);
700 else if (fragP
->fr_subtype
== 7)
702 int offset
= fragP
->fr_fix
;
703 fragP
->fr_literal
[offset
] = 0xf4;
704 fragP
->fr_literal
[offset
+ 1] = 0xe1;
706 fix_new (fragP
, fragP
->fr_fix
+ 2, 4, fragP
->fr_symbol
,
707 fragP
->fr_offset
, 1, BFD_RELOC_24_PCREL
);
711 else if (fragP
->fr_subtype
== 8)
713 fragP
->fr_literal
[fragP
->fr_fix
] = 0xea;
714 fix_new (fragP
, fragP
->fr_fix
+ 1, 1, fragP
->fr_symbol
,
715 fragP
->fr_offset
, 1, BFD_RELOC_8_PCREL
);
719 else if (fragP
->fr_subtype
== 9)
721 int offset
= fragP
->fr_fix
;
722 fragP
->fr_literal
[offset
] = 0xfc;
724 fix_new (fragP
, fragP
->fr_fix
+ 1, 4, fragP
->fr_symbol
,
725 fragP
->fr_offset
, 1, BFD_RELOC_16_PCREL
);
729 else if (fragP
->fr_subtype
== 10)
731 int offset
= fragP
->fr_fix
;
732 fragP
->fr_literal
[offset
] = 0xf4;
733 fragP
->fr_literal
[offset
+ 1] = 0xe0;
735 fix_new (fragP
, fragP
->fr_fix
+ 2, 4, fragP
->fr_symbol
,
736 fragP
->fr_offset
, 1, BFD_RELOC_24_PCREL
);
745 md_section_align (seg
, addr
)
749 int align
= bfd_get_section_alignment (stdoutput
, seg
);
750 return ((addr
+ (1 << align
) - 1) & (-1 << align
));
756 char *prev_name
= "";
757 register const struct mn10200_opcode
*op
;
759 mn10200_hash
= hash_new ();
761 /* Insert unique names into hash table. The MN10200 instruction set
762 has many identical opcode names that have different opcodes based
763 on the operands. This hash table then provides a quick index to
764 the first opcode with a particular name in the opcode table. */
766 op
= mn10200_opcodes
;
769 if (strcmp (prev_name
, op
->name
))
771 prev_name
= (char *) op
->name
;
772 hash_insert (mn10200_hash
, op
->name
, (char *) op
);
777 /* This is both a simplification (we don't have to write md_apply_fix)
778 and support for future optimizations (branch shortening and similar
779 stuff in the linker. */
788 struct mn10200_opcode
*opcode
;
789 struct mn10200_opcode
*next_opcode
;
790 const unsigned char *opindex_ptr
;
791 int next_opindex
, relaxable
;
792 unsigned long insn
, extension
, size
= 0;
797 /* Get the opcode. */
798 for (s
= str
; *s
!= '\0' && !isspace (*s
); s
++)
803 /* Find the first opcode with the proper name. */
804 opcode
= (struct mn10200_opcode
*) hash_find (mn10200_hash
, str
);
807 as_bad (_("Unrecognized opcode: `%s'"), str
);
812 while (isspace (*str
))
815 input_line_pointer
= str
;
819 const char *errmsg
= NULL
;
828 insn
= opcode
->opcode
;
830 for (op_idx
= 1, opindex_ptr
= opcode
->operands
;
832 opindex_ptr
++, op_idx
++)
834 const struct mn10200_operand
*operand
;
837 if (next_opindex
== 0)
839 operand
= &mn10200_operands
[*opindex_ptr
];
843 operand
= &mn10200_operands
[next_opindex
];
849 while (*str
== ' ' || *str
== ',')
852 if (operand
->flags
& MN10200_OPERAND_RELAX
)
855 /* Gather the operand. */
856 hold
= input_line_pointer
;
857 input_line_pointer
= str
;
859 if (operand
->flags
& MN10200_OPERAND_PAREN
)
861 if (*input_line_pointer
!= ')' && *input_line_pointer
!= '(')
863 input_line_pointer
= hold
;
867 input_line_pointer
++;
870 /* See if we can match the operands. */
871 else if (operand
->flags
& MN10200_OPERAND_DREG
)
873 if (!data_register_name (&ex
))
875 input_line_pointer
= hold
;
880 else if (operand
->flags
& MN10200_OPERAND_AREG
)
882 if (!address_register_name (&ex
))
884 input_line_pointer
= hold
;
889 else if (operand
->flags
& MN10200_OPERAND_PSW
)
891 char *start
= input_line_pointer
;
892 char c
= get_symbol_end ();
894 if (strcmp (start
, "psw") != 0)
896 *input_line_pointer
= c
;
897 input_line_pointer
= hold
;
901 *input_line_pointer
= c
;
904 else if (operand
->flags
& MN10200_OPERAND_MDR
)
906 char *start
= input_line_pointer
;
907 char c
= get_symbol_end ();
909 if (strcmp (start
, "mdr") != 0)
911 *input_line_pointer
= c
;
912 input_line_pointer
= hold
;
916 *input_line_pointer
= c
;
919 else if (data_register_name (&ex
))
921 input_line_pointer
= hold
;
925 else if (address_register_name (&ex
))
927 input_line_pointer
= hold
;
931 else if (other_register_name (&ex
))
933 input_line_pointer
= hold
;
937 else if (*str
== ')' || *str
== '(')
939 input_line_pointer
= hold
;
951 errmsg
= _("illegal operand");
954 errmsg
= _("missing operand");
958 & (MN10200_OPERAND_DREG
| MN10200_OPERAND_AREG
)) == 0)
960 input_line_pointer
= hold
;
965 if (opcode
->format
== FMT_2
|| opcode
->format
== FMT_5
)
967 else if (opcode
->format
== FMT_3
|| opcode
->format
== FMT_6
968 || opcode
->format
== FMT_7
)
973 mn10200_insert_operand (&insn
, &extension
, operand
,
974 ex
.X_add_number
, (char *) NULL
,
980 /* If this operand can be promoted, and it doesn't
981 fit into the allocated bitfield for this insn,
982 then promote it (ie this opcode does not match). */
984 & (MN10200_OPERAND_PROMOTE
| MN10200_OPERAND_RELAX
)
985 && !check_operand (insn
, operand
, ex
.X_add_number
))
987 input_line_pointer
= hold
;
992 mn10200_insert_operand (&insn
, &extension
, operand
,
993 ex
.X_add_number
, (char *) NULL
,
998 /* If this operand can be promoted, then this opcode didn't
999 match since we can't know if it needed promotion! */
1000 if (operand
->flags
& MN10200_OPERAND_PROMOTE
)
1002 input_line_pointer
= hold
;
1007 /* We need to generate a fixup for this expression. */
1008 if (fc
>= MAX_INSN_FIXUPS
)
1009 as_fatal (_("too many fixups"));
1010 fixups
[fc
].exp
= ex
;
1011 fixups
[fc
].opindex
= *opindex_ptr
;
1012 fixups
[fc
].reloc
= BFD_RELOC_UNUSED
;
1018 str
= input_line_pointer
;
1019 input_line_pointer
= hold
;
1021 while (*str
== ' ' || *str
== ',')
1026 /* Make sure we used all the operands! */
1033 next_opcode
= opcode
+ 1;
1034 if (!strcmp (next_opcode
->name
, opcode
->name
))
1036 opcode
= next_opcode
;
1040 as_bad ("%s", errmsg
);
1046 while (isspace (*str
))
1050 as_bad (_("junk at end of line: `%s'"), str
);
1052 input_line_pointer
= str
;
1054 if (opcode
->format
== FMT_1
)
1056 else if (opcode
->format
== FMT_2
|| opcode
->format
== FMT_4
)
1058 else if (opcode
->format
== FMT_3
|| opcode
->format
== FMT_5
)
1060 else if (opcode
->format
== FMT_6
)
1062 else if (opcode
->format
== FMT_7
)
1067 /* Write out the instruction. */
1069 if (relaxable
&& fc
> 0)
1074 if (size
== 2 && opcode
->opcode
!= 0xfc0000)
1076 /* Handle bra specially. Basically treat it like jmp so
1077 that we automatically handle 8, 16 and 32 bit offsets
1078 correctly as well as jumps to an undefined address.
1080 It is also important to not treat it like other bCC
1081 instructions since the long forms of bra is different
1082 from other bCC instructions. */
1083 if (opcode
->opcode
== 0xea00)
1089 else if (size
== 3 && opcode
->opcode
== 0xfd0000)
1092 else if (size
== 3 && opcode
->opcode
== 0xfc0000)
1098 f
= frag_var (rs_machine_dependent
, 8, 8 - size
, type
,
1099 fixups
[0].exp
.X_add_symbol
,
1100 fixups
[0].exp
.X_add_number
,
1101 (char *)fixups
[0].opindex
);
1102 number_to_chars_bigendian (f
, insn
, size
);
1105 number_to_chars_bigendian (f
+ size
, 0, 4);
1106 number_to_chars_bigendian (f
+ size
+ 4, 0, 8 - size
- 4);
1109 number_to_chars_bigendian (f
+ size
, 0, 8 - size
);
1114 f
= frag_more (size
);
1116 /* Oh, what a mess. The instruction is in big endian format, but
1117 16 and 24bit immediates are little endian! */
1118 if (opcode
->format
== FMT_3
)
1120 number_to_chars_bigendian (f
, (insn
>> 16) & 0xff, 1);
1121 number_to_chars_littleendian (f
+ 1, insn
& 0xffff, 2);
1123 else if (opcode
->format
== FMT_6
)
1125 number_to_chars_bigendian (f
, (insn
>> 16) & 0xffff, 2);
1126 number_to_chars_littleendian (f
+ 2, insn
& 0xffff, 2);
1128 else if (opcode
->format
== FMT_7
)
1130 number_to_chars_bigendian (f
, (insn
>> 16) & 0xffff, 2);
1131 number_to_chars_littleendian (f
+ 2, insn
& 0xffff, 2);
1132 number_to_chars_littleendian (f
+ 4, extension
& 0xff, 1);
1136 number_to_chars_bigendian (f
, insn
, size
> 4 ? 4 : size
);
1139 /* Create any fixups. */
1140 for (i
= 0; i
< fc
; i
++)
1142 const struct mn10200_operand
*operand
;
1144 operand
= &mn10200_operands
[fixups
[i
].opindex
];
1145 if (fixups
[i
].reloc
!= BFD_RELOC_UNUSED
)
1147 reloc_howto_type
*reloc_howto
;
1152 reloc_howto
= bfd_reloc_type_lookup (stdoutput
,
1158 size
= bfd_get_reloc_size (reloc_howto
);
1160 if (size
< 1 || size
> 4)
1164 fixP
= fix_new_exp (frag_now
, f
- frag_now
->fr_literal
+ offset
,
1167 reloc_howto
->pc_relative
,
1170 /* PC-relative offsets are from the first byte of the
1171 next instruction, not from the start of the current
1173 if (reloc_howto
->pc_relative
)
1174 fixP
->fx_offset
+= size
;
1178 int reloc
, pcrel
, reloc_size
, offset
;
1181 reloc
= BFD_RELOC_NONE
;
1182 /* How big is the reloc? Remember SPLIT relocs are
1183 implicitly 32bits. */
1184 reloc_size
= operand
->bits
;
1186 offset
= size
- reloc_size
/ 8;
1188 /* Is the reloc pc-relative? */
1189 pcrel
= (operand
->flags
& MN10200_OPERAND_PCREL
) != 0;
1191 /* Choose a proper BFD relocation type. */
1194 if (reloc_size
== 8)
1195 reloc
= BFD_RELOC_8_PCREL
;
1196 else if (reloc_size
== 24)
1197 reloc
= BFD_RELOC_24_PCREL
;
1203 if (reloc_size
== 32)
1204 reloc
= BFD_RELOC_32
;
1205 else if (reloc_size
== 16)
1206 reloc
= BFD_RELOC_16
;
1207 else if (reloc_size
== 8)
1208 reloc
= BFD_RELOC_8
;
1209 else if (reloc_size
== 24)
1210 reloc
= BFD_RELOC_24
;
1215 /* Convert the size of the reloc into what fix_new_exp
1217 reloc_size
= reloc_size
/ 8;
1218 if (reloc_size
== 8)
1220 else if (reloc_size
== 16)
1222 else if (reloc_size
== 32 || reloc_size
== 24)
1225 fixP
= fix_new_exp (frag_now
, f
- frag_now
->fr_literal
+ offset
,
1226 reloc_size
, &fixups
[i
].exp
, pcrel
,
1227 ((bfd_reloc_code_real_type
) reloc
));
1229 /* PC-relative offsets are from the first byte of the
1230 next instruction, not from the start of the current
1233 fixP
->fx_offset
+= size
;
1239 /* If while processing a fixup, a reloc really needs to be created
1240 Then it is done here. */
1243 tc_gen_reloc (seg
, fixp
)
1248 reloc
= (arelent
*) xmalloc (sizeof (arelent
));
1250 reloc
->howto
= bfd_reloc_type_lookup (stdoutput
, fixp
->fx_r_type
);
1251 if (reloc
->howto
== (reloc_howto_type
*) NULL
)
1253 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
1254 _("reloc %d not supported by object file format"),
1255 (int) fixp
->fx_r_type
);
1258 reloc
->address
= fixp
->fx_frag
->fr_address
+ fixp
->fx_where
;
1260 if (fixp
->fx_addsy
&& fixp
->fx_subsy
)
1262 if ((S_GET_SEGMENT (fixp
->fx_addsy
) != S_GET_SEGMENT (fixp
->fx_subsy
))
1263 || S_GET_SEGMENT (fixp
->fx_addsy
) == undefined_section
)
1265 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
1266 "Difference of symbols in different sections is not supported");
1269 reloc
->sym_ptr_ptr
= &bfd_abs_symbol
;
1270 reloc
->addend
= (S_GET_VALUE (fixp
->fx_addsy
)
1271 - S_GET_VALUE (fixp
->fx_subsy
) + fixp
->fx_offset
);
1275 reloc
->sym_ptr_ptr
= (asymbol
**) xmalloc (sizeof (asymbol
*));
1276 *reloc
->sym_ptr_ptr
= symbol_get_bfdsym (fixp
->fx_addsy
);
1277 reloc
->addend
= fixp
->fx_offset
;
1283 md_estimate_size_before_relax (fragp
, seg
)
1287 if (fragp
->fr_subtype
== 0)
1289 if (fragp
->fr_subtype
== 3)
1291 if (fragp
->fr_subtype
== 6)
1293 if (!S_IS_DEFINED (fragp
->fr_symbol
)
1294 || seg
!= S_GET_SEGMENT (fragp
->fr_symbol
))
1296 fragp
->fr_subtype
= 7;
1301 if (fragp
->fr_subtype
== 8)
1303 if (!S_IS_DEFINED (fragp
->fr_symbol
))
1305 fragp
->fr_subtype
= 10;
1313 md_pcrel_from (fixp
)
1316 return fixp
->fx_frag
->fr_address
;
1318 if (fixp
->fx_addsy
!= (symbolS
*) NULL
&& !S_IS_DEFINED (fixp
->fx_addsy
))
1320 /* The symbol is undefined. Let the linker figure it out. */
1323 return fixp
->fx_frag
->fr_address
+ fixp
->fx_where
;
1328 md_apply_fix3 (fixp
, valuep
, seg
)
1333 /* We shouldn't ever get here because linkrelax is nonzero. */
1339 /* Insert an operand value into an instruction. */
1342 mn10200_insert_operand (insnp
, extensionp
, operand
, val
, file
, line
, shift
)
1343 unsigned long *insnp
;
1344 unsigned long *extensionp
;
1345 const struct mn10200_operand
*operand
;
1351 /* No need to check 24 or 32bit operands for a bit. */
1352 if (operand
->bits
< 24
1353 && (operand
->flags
& MN10200_OPERAND_NOCHECK
) == 0)
1358 if ((operand
->flags
& MN10200_OPERAND_SIGNED
) != 0)
1360 max
= (1 << (operand
->bits
- 1)) - 1;
1361 min
= - (1 << (operand
->bits
- 1));
1365 max
= (1 << operand
->bits
) - 1;
1371 if (test
< (offsetT
) min
|| test
> (offsetT
) max
)
1374 _("operand out of range (%s not between %ld and %ld)");
1377 sprint_value (buf
, test
);
1378 if (file
== (char *) NULL
)
1379 as_warn (err
, buf
, min
, max
);
1381 as_warn_where (file
, line
, err
, buf
, min
, max
);
1385 if ((operand
->flags
& MN10200_OPERAND_EXTENDED
) == 0)
1387 *insnp
|= (((long) val
& ((1 << operand
->bits
) - 1))
1388 << (operand
->shift
+ shift
));
1390 if ((operand
->flags
& MN10200_OPERAND_REPEATED
) != 0)
1391 *insnp
|= (((long) val
& ((1 << operand
->bits
) - 1))
1392 << (operand
->shift
+ shift
+ 2));
1396 *extensionp
|= (val
>> 16) & 0xff;
1397 *insnp
|= val
& 0xffff;
1401 static unsigned long
1402 check_operand (insn
, operand
, val
)
1404 const struct mn10200_operand
*operand
;
1407 /* No need to check 24bit or 32bit operands for a bit. */
1408 if (operand
->bits
< 24
1409 && (operand
->flags
& MN10200_OPERAND_NOCHECK
) == 0)
1414 if ((operand
->flags
& MN10200_OPERAND_SIGNED
) != 0)
1416 max
= (1 << (operand
->bits
- 1)) - 1;
1417 min
= - (1 << (operand
->bits
- 1));
1421 max
= (1 << operand
->bits
) - 1;
1427 if (test
< (offsetT
) min
|| test
> (offsetT
) max
)