1 /* tc-mn10200.c -- Assembler code for the Matsushita 10200
2 Copyright (C) 1996-2022 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 "opcode/mn10200.h"
26 /* Structure to hold information about predefined registers. */
33 /* Generic assembler global variables which must be defined by all
36 /* Characters which always start a comment. */
37 const char comment_chars
[] = "#";
39 /* Characters which start a comment at the beginning of a line. */
40 const char line_comment_chars
[] = ";#";
42 /* Characters which may be used to separate multiple commands on a
44 const char line_separator_chars
[] = ";";
46 /* Characters which are used to indicate an exponent in a floating
48 const char EXP_CHARS
[] = "eE";
50 /* Characters which mean that a number is a floating point constant,
52 const char FLT_CHARS
[] = "dD";
54 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},
76 #define MAX_INSN_FIXUPS 5
82 bfd_reloc_code_real_type reloc
;
85 struct mn10200_fixup fixups
[MAX_INSN_FIXUPS
];
88 const char *md_shortopts
= "";
90 struct option md_longopts
[] =
92 {NULL
, no_argument
, NULL
, 0}
95 size_t md_longopts_size
= sizeof (md_longopts
);
97 /* The target specific pseudo-ops which we support. */
98 const pseudo_typeS md_pseudo_table
[] =
103 /* Opcode hash table. */
104 static htab_t mn10200_hash
;
106 /* This table is sorted. Suitable for searching by a binary search. */
107 static const struct reg_name data_registers
[] =
114 #define DATA_REG_NAME_CNT \
115 (sizeof (data_registers) / sizeof (struct reg_name))
117 static const struct reg_name address_registers
[] =
124 #define ADDRESS_REG_NAME_CNT \
125 (sizeof (address_registers) / sizeof (struct reg_name))
127 static const struct reg_name other_registers
[] =
132 #define OTHER_REG_NAME_CNT \
133 (sizeof (other_registers) / sizeof (struct reg_name))
135 /* reg_name_search does a binary search of the given register table
136 to see if "name" is a valid register name. Returns the register
137 number from the array on success, or -1 on failure. */
140 reg_name_search (const struct reg_name
*regs
,
144 int middle
, low
, high
;
152 middle
= (low
+ high
) / 2;
153 cmp
= strcasecmp (name
, regs
[middle
].name
);
159 return regs
[middle
].value
;
165 /* Summary of register_name().
167 in: Input_line_pointer points to 1st char of operand.
170 The operand may have been a register: in this case, X_op == O_register,
171 X_add_number is set to the register number, and truth is returned.
172 Input_line_pointer->(next non-blank) char after operand, or is in
173 its original state. */
176 data_register_name (expressionS
*expressionP
)
183 /* Find the spelling of the operand. */
184 start
= input_line_pointer
;
185 c
= get_symbol_name (&name
);
186 reg_number
= reg_name_search (data_registers
, DATA_REG_NAME_CNT
, name
);
188 /* Put back the delimiting char. */
189 (void) restore_line_pointer (c
);
191 /* Look to see if it's in the register table. */
194 expressionP
->X_op
= O_register
;
195 expressionP
->X_add_number
= reg_number
;
197 /* Make the rest nice. */
198 expressionP
->X_add_symbol
= NULL
;
199 expressionP
->X_op_symbol
= NULL
;
204 /* Reset the line as if we had not done anything. */
205 input_line_pointer
= start
;
209 /* Summary of register_name().
211 in: Input_line_pointer points to 1st char of operand.
214 The operand may have been a register: in this case, X_op == O_register,
215 X_add_number is set to the register number, and truth is returned.
216 Input_line_pointer->(next non-blank) char after operand, or is in
217 its original state. */
220 address_register_name (expressionS
*expressionP
)
227 /* Find the spelling of the operand. */
228 start
= input_line_pointer
;
229 c
= get_symbol_name (&name
);
230 reg_number
= reg_name_search (address_registers
, ADDRESS_REG_NAME_CNT
, name
);
232 /* Put back the delimiting char. */
233 (void) restore_line_pointer (c
);
235 /* Look to see if it's in the register table. */
238 expressionP
->X_op
= O_register
;
239 expressionP
->X_add_number
= reg_number
;
241 /* Make the rest nice. */
242 expressionP
->X_add_symbol
= NULL
;
243 expressionP
->X_op_symbol
= NULL
;
248 /* Reset the line as if we had not done anything. */
249 input_line_pointer
= start
;
253 /* Summary of register_name().
255 in: Input_line_pointer points to 1st char of operand.
258 The operand may have been a register: in this case, X_op == O_register,
259 X_add_number is set to the register number, and truth is returned.
260 Input_line_pointer->(next non-blank) char after operand, or is in
261 its original state. */
264 other_register_name (expressionS
*expressionP
)
271 /* Find the spelling of the operand. */
272 start
= input_line_pointer
;
273 c
= get_symbol_name (&name
);
274 reg_number
= reg_name_search (other_registers
, OTHER_REG_NAME_CNT
, name
);
276 /* Put back the delimiting char. */
277 (void) restore_line_pointer (c
);
279 /* Look to see if it's in the register table. */
282 expressionP
->X_op
= O_register
;
283 expressionP
->X_add_number
= reg_number
;
285 /* Make the rest nice. */
286 expressionP
->X_add_symbol
= NULL
;
287 expressionP
->X_op_symbol
= NULL
;
292 /* Reset the line as if we had not done anything. */
293 input_line_pointer
= start
;
298 md_show_usage (FILE *stream
)
300 fprintf (stream
, _("MN10200 options:\n\
305 md_parse_option (int c ATTRIBUTE_UNUSED
,
306 const char *arg ATTRIBUTE_UNUSED
)
312 md_undefined_symbol (char *name ATTRIBUTE_UNUSED
)
318 md_atof (int type
, char *litp
, int *sizep
)
320 return ieee_md_atof (type
, litp
, sizep
, false);
324 md_convert_frag (bfd
*abfd ATTRIBUTE_UNUSED
,
328 static unsigned long label_count
= 0;
331 subseg_change (sec
, 0);
332 if (fragP
->fr_subtype
== 0)
334 fix_new (fragP
, fragP
->fr_fix
+ 1, 1, fragP
->fr_symbol
,
335 fragP
->fr_offset
, 1, BFD_RELOC_8_PCREL
);
339 else if (fragP
->fr_subtype
== 1)
341 /* Reverse the condition of the first branch. */
342 int offset
= fragP
->fr_fix
;
343 int opcode
= fragP
->fr_literal
[offset
] & 0xff;
380 fragP
->fr_literal
[offset
] = opcode
;
382 /* Create a fixup for the reversed conditional branch. */
383 sprintf (buf
, ".%s_%ld", FAKE_LABEL_NAME
, label_count
++);
384 fix_new (fragP
, fragP
->fr_fix
+ 1, 1,
385 symbol_new (buf
, sec
, fragP
->fr_next
, 0),
386 fragP
->fr_offset
, 1, BFD_RELOC_8_PCREL
);
388 /* Now create the unconditional branch + fixup to the
390 fragP
->fr_literal
[offset
+ 2] = 0xfc;
391 fix_new (fragP
, fragP
->fr_fix
+ 3, 2, fragP
->fr_symbol
,
392 fragP
->fr_offset
, 1, BFD_RELOC_16_PCREL
);
396 else if (fragP
->fr_subtype
== 2)
398 /* Reverse the condition of the first branch. */
399 int offset
= fragP
->fr_fix
;
400 int opcode
= fragP
->fr_literal
[offset
] & 0xff;
437 fragP
->fr_literal
[offset
] = opcode
;
439 /* Create a fixup for the reversed conditional branch. */
440 sprintf (buf
, ".%s_%ld", FAKE_LABEL_NAME
, label_count
++);
441 fix_new (fragP
, fragP
->fr_fix
+ 1, 1,
442 symbol_new (buf
, sec
, fragP
->fr_next
, 0),
443 fragP
->fr_offset
, 1, BFD_RELOC_8_PCREL
);
445 /* Now create the unconditional branch + fixup to the
447 fragP
->fr_literal
[offset
+ 2] = 0xf4;
448 fragP
->fr_literal
[offset
+ 3] = 0xe0;
449 fix_new (fragP
, fragP
->fr_fix
+ 4, 4, fragP
->fr_symbol
,
450 fragP
->fr_offset
, 1, BFD_RELOC_24_PCREL
);
454 else if (fragP
->fr_subtype
== 3)
456 fix_new (fragP
, fragP
->fr_fix
+ 2, 1, fragP
->fr_symbol
,
457 fragP
->fr_offset
, 1, BFD_RELOC_8_PCREL
);
461 else if (fragP
->fr_subtype
== 4)
463 /* Reverse the condition of the first branch. */
464 int offset
= fragP
->fr_fix
;
465 int opcode
= fragP
->fr_literal
[offset
+ 1] & 0xff;
526 fragP
->fr_literal
[offset
+ 1] = opcode
;
528 /* Create a fixup for the reversed conditional branch. */
529 sprintf (buf
, ".%s_%ld", FAKE_LABEL_NAME
, label_count
++);
530 fix_new (fragP
, fragP
->fr_fix
+ 2, 1,
531 symbol_new (buf
, sec
, fragP
->fr_next
, 0),
532 fragP
->fr_offset
, 1, BFD_RELOC_8_PCREL
);
534 /* Now create the unconditional branch + fixup to the
536 fragP
->fr_literal
[offset
+ 3] = 0xfc;
537 fix_new (fragP
, fragP
->fr_fix
+ 4, 2, fragP
->fr_symbol
,
538 fragP
->fr_offset
, 1, BFD_RELOC_16_PCREL
);
542 else if (fragP
->fr_subtype
== 5)
544 /* Reverse the condition of the first branch. */
545 int offset
= fragP
->fr_fix
;
546 int opcode
= fragP
->fr_literal
[offset
+ 1] & 0xff;
607 fragP
->fr_literal
[offset
+ 1] = opcode
;
609 /* Create a fixup for the reversed conditional branch. */
610 sprintf (buf
, ".%s_%ld", FAKE_LABEL_NAME
, label_count
++);
611 fix_new (fragP
, fragP
->fr_fix
+ 2, 1,
612 symbol_new (buf
, sec
, fragP
->fr_next
, 0),
613 fragP
->fr_offset
, 1, BFD_RELOC_8_PCREL
);
615 /* Now create the unconditional branch + fixup to the
617 fragP
->fr_literal
[offset
+ 3] = 0xf4;
618 fragP
->fr_literal
[offset
+ 4] = 0xe0;
619 fix_new (fragP
, fragP
->fr_fix
+ 5, 4, fragP
->fr_symbol
,
620 fragP
->fr_offset
, 1, BFD_RELOC_24_PCREL
);
624 else if (fragP
->fr_subtype
== 6)
626 fix_new (fragP
, fragP
->fr_fix
+ 1, 2, fragP
->fr_symbol
,
627 fragP
->fr_offset
, 1, BFD_RELOC_16_PCREL
);
631 else if (fragP
->fr_subtype
== 7)
633 int offset
= fragP
->fr_fix
;
634 fragP
->fr_literal
[offset
] = 0xf4;
635 fragP
->fr_literal
[offset
+ 1] = 0xe1;
637 fix_new (fragP
, fragP
->fr_fix
+ 2, 4, fragP
->fr_symbol
,
638 fragP
->fr_offset
, 1, BFD_RELOC_24_PCREL
);
642 else if (fragP
->fr_subtype
== 8)
644 fragP
->fr_literal
[fragP
->fr_fix
] = 0xea;
645 fix_new (fragP
, fragP
->fr_fix
+ 1, 1, fragP
->fr_symbol
,
646 fragP
->fr_offset
, 1, BFD_RELOC_8_PCREL
);
650 else if (fragP
->fr_subtype
== 9)
652 int offset
= fragP
->fr_fix
;
653 fragP
->fr_literal
[offset
] = 0xfc;
655 fix_new (fragP
, fragP
->fr_fix
+ 1, 4, fragP
->fr_symbol
,
656 fragP
->fr_offset
, 1, BFD_RELOC_16_PCREL
);
660 else if (fragP
->fr_subtype
== 10)
662 int offset
= fragP
->fr_fix
;
663 fragP
->fr_literal
[offset
] = 0xf4;
664 fragP
->fr_literal
[offset
+ 1] = 0xe0;
666 fix_new (fragP
, fragP
->fr_fix
+ 2, 4, fragP
->fr_symbol
,
667 fragP
->fr_offset
, 1, BFD_RELOC_24_PCREL
);
676 md_section_align (asection
*seg
, valueT addr
)
678 int align
= bfd_section_alignment (seg
);
679 return ((addr
+ (1 << align
) - 1) & -(1 << align
));
685 const char *prev_name
= "";
686 const struct mn10200_opcode
*op
;
688 mn10200_hash
= str_htab_create ();
690 /* Insert unique names into hash table. The MN10200 instruction set
691 has many identical opcode names that have different opcodes based
692 on the operands. This hash table then provides a quick index to
693 the first opcode with a particular name in the opcode table. */
695 op
= mn10200_opcodes
;
698 if (strcmp (prev_name
, op
->name
))
700 prev_name
= (char *) op
->name
;
701 str_hash_insert (mn10200_hash
, op
->name
, op
, 0);
706 /* This is both a simplification (we don't have to write md_apply_fix)
707 and support for future optimizations (branch shortening and similar
708 stuff in the linker. */
713 check_operand (unsigned long insn ATTRIBUTE_UNUSED
,
714 const struct mn10200_operand
*operand
,
717 /* No need to check 24bit or 32bit operands for a bit. */
718 if (operand
->bits
< 24
719 && (operand
->flags
& MN10200_OPERAND_NOCHECK
) == 0)
724 if ((operand
->flags
& MN10200_OPERAND_SIGNED
) != 0)
726 max
= (1 << (operand
->bits
- 1)) - 1;
727 min
= - (1 << (operand
->bits
- 1));
731 max
= (1 << operand
->bits
) - 1;
737 if (test
< (offsetT
) min
|| test
> (offsetT
) max
)
744 /* If while processing a fixup, a reloc really needs to be created
745 Then it is done here. */
748 tc_gen_reloc (asection
*seg ATTRIBUTE_UNUSED
, fixS
*fixp
)
751 reloc
= XNEW (arelent
);
753 if (fixp
->fx_subsy
!= NULL
)
755 if (S_GET_SEGMENT (fixp
->fx_addsy
) == S_GET_SEGMENT (fixp
->fx_subsy
)
756 && S_IS_DEFINED (fixp
->fx_subsy
))
758 fixp
->fx_offset
-= S_GET_VALUE (fixp
->fx_subsy
);
759 fixp
->fx_subsy
= NULL
;
762 /* FIXME: We should try more ways to resolve difference expressions
763 here. At least this is better than silently ignoring the
765 as_bad_subtract (fixp
);
768 reloc
->howto
= bfd_reloc_type_lookup (stdoutput
, fixp
->fx_r_type
);
769 if (reloc
->howto
== NULL
)
771 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
772 _("reloc %d not supported by object file format"),
773 (int) fixp
->fx_r_type
);
776 reloc
->address
= fixp
->fx_frag
->fr_address
+ fixp
->fx_where
;
777 reloc
->sym_ptr_ptr
= XNEW (asymbol
*);
778 *reloc
->sym_ptr_ptr
= symbol_get_bfdsym (fixp
->fx_addsy
);
779 reloc
->addend
= fixp
->fx_offset
;
784 md_estimate_size_before_relax (fragS
*fragp
, asection
*seg
)
786 if (fragp
->fr_subtype
== 6
787 && (!S_IS_DEFINED (fragp
->fr_symbol
)
788 || seg
!= S_GET_SEGMENT (fragp
->fr_symbol
)))
789 fragp
->fr_subtype
= 7;
790 else if (fragp
->fr_subtype
== 8
791 && (!S_IS_DEFINED (fragp
->fr_symbol
)
792 || seg
!= S_GET_SEGMENT (fragp
->fr_symbol
)))
793 fragp
->fr_subtype
= 10;
795 if (fragp
->fr_subtype
>= sizeof (md_relax_table
) / sizeof (md_relax_table
[0]))
798 return md_relax_table
[fragp
->fr_subtype
].rlx_length
;
802 md_pcrel_from (fixS
*fixp
)
804 return fixp
->fx_frag
->fr_address
;
808 md_apply_fix (fixS
* fixP
, valueT
* valP ATTRIBUTE_UNUSED
, segT seg ATTRIBUTE_UNUSED
)
810 /* We shouldn't ever get here because linkrelax is nonzero. */
815 /* Insert an operand value into an instruction. */
818 mn10200_insert_operand (unsigned long *insnp
,
819 unsigned long *extensionp
,
820 const struct mn10200_operand
*operand
,
826 /* No need to check 24 or 32bit operands for a bit. */
827 if (operand
->bits
< 24
828 && (operand
->flags
& MN10200_OPERAND_NOCHECK
) == 0)
833 if ((operand
->flags
& MN10200_OPERAND_SIGNED
) != 0)
835 max
= (1 << (operand
->bits
- 1)) - 1;
836 min
= - (1 << (operand
->bits
- 1));
840 max
= (1 << operand
->bits
) - 1;
846 if (test
< (offsetT
) min
|| test
> (offsetT
) max
)
847 as_warn_value_out_of_range (_("operand"), test
, (offsetT
) min
, (offsetT
) max
, file
, line
);
850 if ((operand
->flags
& MN10200_OPERAND_EXTENDED
) == 0)
852 *insnp
|= (((long) val
& ((1 << operand
->bits
) - 1))
853 << (operand
->shift
+ shift
));
855 if ((operand
->flags
& MN10200_OPERAND_REPEATED
) != 0)
856 *insnp
|= (((long) val
& ((1 << operand
->bits
) - 1))
857 << (operand
->shift
+ shift
+ 2));
861 *extensionp
|= (val
>> 16) & 0xff;
862 *insnp
|= val
& 0xffff;
867 md_assemble (char *str
)
870 struct mn10200_opcode
*opcode
;
871 struct mn10200_opcode
*next_opcode
;
872 const unsigned char *opindex_ptr
;
873 int next_opindex
, relaxable
;
874 unsigned long insn
, extension
, size
= 0;
879 /* Get the opcode. */
880 for (s
= str
; *s
!= '\0' && !ISSPACE (*s
); s
++)
885 /* Find the first opcode with the proper name. */
886 opcode
= (struct mn10200_opcode
*) str_hash_find (mn10200_hash
, str
);
889 as_bad (_("Unrecognized opcode: `%s'"), str
);
894 while (ISSPACE (*str
))
897 input_line_pointer
= str
;
901 const char *errmsg
= NULL
;
910 insn
= opcode
->opcode
;
912 for (op_idx
= 1, opindex_ptr
= opcode
->operands
;
914 opindex_ptr
++, op_idx
++)
916 const struct mn10200_operand
*operand
;
919 if (next_opindex
== 0)
921 operand
= &mn10200_operands
[*opindex_ptr
];
925 operand
= &mn10200_operands
[next_opindex
];
931 while (*str
== ' ' || *str
== ',')
934 if (operand
->flags
& MN10200_OPERAND_RELAX
)
937 /* Gather the operand. */
938 hold
= input_line_pointer
;
939 input_line_pointer
= str
;
941 if (operand
->flags
& MN10200_OPERAND_PAREN
)
943 if (*input_line_pointer
!= ')' && *input_line_pointer
!= '(')
945 input_line_pointer
= hold
;
949 input_line_pointer
++;
952 /* See if we can match the operands. */
953 else if (operand
->flags
& MN10200_OPERAND_DREG
)
955 if (!data_register_name (&ex
))
957 input_line_pointer
= hold
;
962 else if (operand
->flags
& MN10200_OPERAND_AREG
)
964 if (!address_register_name (&ex
))
966 input_line_pointer
= hold
;
971 else if (operand
->flags
& MN10200_OPERAND_PSW
)
974 char c
= get_symbol_name (&start
);
976 if (strcmp (start
, "psw") != 0)
978 (void) restore_line_pointer (c
);
979 input_line_pointer
= hold
;
983 (void) restore_line_pointer (c
);
986 else if (operand
->flags
& MN10200_OPERAND_MDR
)
989 char c
= get_symbol_name (&start
);
991 if (strcmp (start
, "mdr") != 0)
993 (void) restore_line_pointer (c
);
994 input_line_pointer
= hold
;
998 (void) restore_line_pointer (c
);
1001 else if (data_register_name (&ex
))
1003 input_line_pointer
= hold
;
1007 else if (address_register_name (&ex
))
1009 input_line_pointer
= hold
;
1013 else if (other_register_name (&ex
))
1015 input_line_pointer
= hold
;
1019 else if (*str
== ')' || *str
== '(')
1021 input_line_pointer
= hold
;
1033 errmsg
= _("illegal operand");
1036 errmsg
= _("missing operand");
1040 & (MN10200_OPERAND_DREG
| MN10200_OPERAND_AREG
)) == 0)
1042 input_line_pointer
= hold
;
1047 if (opcode
->format
== FMT_2
|| opcode
->format
== FMT_5
)
1049 else if (opcode
->format
== FMT_3
|| opcode
->format
== FMT_6
1050 || opcode
->format
== FMT_7
)
1055 mn10200_insert_operand (&insn
, &extension
, operand
,
1056 ex
.X_add_number
, NULL
,
1062 /* If this operand can be promoted, and it doesn't
1063 fit into the allocated bitfield for this insn,
1064 then promote it (ie this opcode does not match). */
1066 & (MN10200_OPERAND_PROMOTE
| MN10200_OPERAND_RELAX
)
1067 && !check_operand (insn
, operand
, ex
.X_add_number
))
1069 input_line_pointer
= hold
;
1074 mn10200_insert_operand (&insn
, &extension
, operand
,
1075 ex
.X_add_number
, NULL
,
1080 /* If this operand can be promoted, then this opcode didn't
1081 match since we can't know if it needed promotion! */
1082 if (operand
->flags
& MN10200_OPERAND_PROMOTE
)
1084 input_line_pointer
= hold
;
1089 /* We need to generate a fixup for this expression. */
1090 if (fc
>= MAX_INSN_FIXUPS
)
1091 as_fatal (_("too many fixups"));
1092 fixups
[fc
].exp
= ex
;
1093 fixups
[fc
].opindex
= *opindex_ptr
;
1094 fixups
[fc
].reloc
= BFD_RELOC_UNUSED
;
1100 str
= input_line_pointer
;
1101 input_line_pointer
= hold
;
1103 while (*str
== ' ' || *str
== ',')
1108 /* Make sure we used all the operands! */
1115 next_opcode
= opcode
+ 1;
1116 if (!strcmp (next_opcode
->name
, opcode
->name
))
1118 opcode
= next_opcode
;
1122 as_bad ("%s", errmsg
);
1128 while (ISSPACE (*str
))
1132 as_bad (_("junk at end of line: `%s'"), str
);
1134 input_line_pointer
= str
;
1136 if (opcode
->format
== FMT_1
)
1138 else if (opcode
->format
== FMT_2
|| opcode
->format
== FMT_4
)
1140 else if (opcode
->format
== FMT_3
|| opcode
->format
== FMT_5
)
1142 else if (opcode
->format
== FMT_6
)
1144 else if (opcode
->format
== FMT_7
)
1149 /* Write out the instruction. */
1150 dwarf2_emit_insn (size
);
1151 if (relaxable
&& fc
> 0)
1153 /* On a 64-bit host the size of an 'int' is not the same
1154 as the size of a pointer, so we need a union to convert
1155 the opindex field of the fr_cgen structure into a char *
1156 so that it can be stored in the frag. We do not have
1157 to worry about losing accuracy as we are not going to
1158 be even close to the 32bit limit of the int. */
1168 if (size
== 2 && opcode
->opcode
!= 0xfc0000)
1170 /* Handle bra specially. Basically treat it like jmp so
1171 that we automatically handle 8, 16 and 32 bit offsets
1172 correctly as well as jumps to an undefined address.
1174 It is also important to not treat it like other bCC
1175 instructions since the long forms of bra is different
1176 from other bCC instructions. */
1177 if (opcode
->opcode
== 0xea00)
1183 else if (size
== 3 && opcode
->opcode
== 0xfd0000)
1186 else if (size
== 3 && opcode
->opcode
== 0xfc0000)
1192 opindex_converter
.opindex
= fixups
[0].opindex
;
1193 f
= frag_var (rs_machine_dependent
, 8, 8 - size
, type
,
1194 fixups
[0].exp
.X_add_symbol
,
1195 fixups
[0].exp
.X_add_number
,
1196 opindex_converter
.ptr
);
1197 number_to_chars_bigendian (f
, insn
, size
);
1200 number_to_chars_bigendian (f
+ size
, 0, 4);
1201 number_to_chars_bigendian (f
+ size
+ 4, 0, 8 - size
- 4);
1204 number_to_chars_bigendian (f
+ size
, 0, 8 - size
);
1208 f
= frag_more (size
);
1210 /* Oh, what a mess. The instruction is in big endian format, but
1211 16 and 24bit immediates are little endian! */
1212 if (opcode
->format
== FMT_3
)
1214 number_to_chars_bigendian (f
, (insn
>> 16) & 0xff, 1);
1215 number_to_chars_littleendian (f
+ 1, insn
& 0xffff, 2);
1217 else if (opcode
->format
== FMT_6
)
1219 number_to_chars_bigendian (f
, (insn
>> 16) & 0xffff, 2);
1220 number_to_chars_littleendian (f
+ 2, insn
& 0xffff, 2);
1222 else if (opcode
->format
== FMT_7
)
1224 number_to_chars_bigendian (f
, (insn
>> 16) & 0xffff, 2);
1225 number_to_chars_littleendian (f
+ 2, insn
& 0xffff, 2);
1226 number_to_chars_littleendian (f
+ 4, extension
& 0xff, 1);
1229 number_to_chars_bigendian (f
, insn
, size
> 4 ? 4 : size
);
1231 /* Create any fixups. */
1232 for (i
= 0; i
< fc
; i
++)
1234 const struct mn10200_operand
*operand
;
1237 operand
= &mn10200_operands
[fixups
[i
].opindex
];
1238 if (fixups
[i
].reloc
!= BFD_RELOC_UNUSED
)
1240 reloc_howto_type
*reloc_howto
;
1244 reloc_howto
= bfd_reloc_type_lookup (stdoutput
,
1250 reloc_size
= bfd_get_reloc_size (reloc_howto
);
1252 if (reloc_size
< 1 || reloc_size
> 4)
1255 offset
= 4 - reloc_size
;
1256 fixP
= fix_new_exp (frag_now
, f
- frag_now
->fr_literal
+ offset
,
1259 reloc_howto
->pc_relative
,
1262 /* PC-relative offsets are from the first byte of the
1263 next instruction, not from the start of the current
1265 if (reloc_howto
->pc_relative
)
1266 fixP
->fx_offset
+= reloc_size
;
1270 int reloc
, pcrel
, offset
;
1273 reloc
= BFD_RELOC_NONE
;
1274 /* How big is the reloc? Remember SPLIT relocs are
1275 implicitly 32bits. */
1276 reloc_size
= operand
->bits
;
1278 offset
= size
- reloc_size
/ 8;
1280 /* Is the reloc pc-relative? */
1281 pcrel
= (operand
->flags
& MN10200_OPERAND_PCREL
) != 0;
1283 /* Choose a proper BFD relocation type. */
1286 if (reloc_size
== 8)
1287 reloc
= BFD_RELOC_8_PCREL
;
1288 else if (reloc_size
== 24)
1289 reloc
= BFD_RELOC_24_PCREL
;
1295 if (reloc_size
== 32)
1296 reloc
= BFD_RELOC_32
;
1297 else if (reloc_size
== 16)
1298 reloc
= BFD_RELOC_16
;
1299 else if (reloc_size
== 8)
1300 reloc
= BFD_RELOC_8
;
1301 else if (reloc_size
== 24)
1302 reloc
= BFD_RELOC_24
;
1307 /* Convert the size of the reloc into what fix_new_exp
1309 reloc_size
= reloc_size
/ 8;
1310 if (reloc_size
== 8)
1312 else if (reloc_size
== 16)
1314 else if (reloc_size
== 32 || reloc_size
== 24)
1317 fixP
= fix_new_exp (frag_now
, f
- frag_now
->fr_literal
+ offset
,
1318 reloc_size
, &fixups
[i
].exp
, pcrel
,
1319 ((bfd_reloc_code_real_type
) reloc
));
1321 /* PC-relative offsets are from the first byte of the
1322 next instruction, not from the start of the current
1325 fixP
->fx_offset
+= size
;