Add missing fpcmp instructions, and add missing fcmp/fpcmp tests.
[binutils.git] / bfd / coff-mcore.c
blobf20c2ca815f49e664de281c90a67a4d9ef80395f
1 /* BFD back-end for Motorola MCore COFF/PE
2 Copyright (C) 1999 Free Software Foundation, Inc.
4 This file is part of BFD, the Binary File Descriptor library.
6 This program 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 of the License, or
9 (at your option) any later version.
11 This program 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 this program; if not, write to the Free Software
18 Foundation, 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
21 #include "bfd.h"
22 #include "sysdep.h"
23 #include "libbfd.h"
24 #include "coff/mcore.h"
25 #include "coff/internal.h"
26 #include "coff/pe.h"
27 #include "libcoff.h"
29 #ifdef BADMAG
30 #undef BADMAG
31 #endif
32 #define BADMAG(x) MCOREBADMAG(x)
34 #ifndef NUM_ELEM
35 #define NUM_ELEM(A) (sizeof (A) / sizeof (A)[0])
36 #endif
38 /* This file is compiled more than once, but we only compile the
39 final_link routine once. */
40 extern boolean mcore_bfd_coff_final_link
41 PARAMS ((bfd *, struct bfd_link_info *));
43 static struct bfd_link_hash_table * coff_mcore_link_hash_table_create
44 PARAMS ((bfd *));
45 static bfd_reloc_status_type mcore_coff_unsupported_reloc
46 PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
47 static boolean coff_mcore_relocate_section
48 PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
49 struct internal_reloc *, struct internal_syment *, asection **));
50 static reloc_howto_type * mcore_coff_reloc_type_lookup
51 PARAMS ((bfd *, bfd_reloc_code_real_type));
52 static reloc_howto_type * coff_mcore_rtype_to_howto
53 PARAMS ((bfd *, asection *, struct internal_reloc *,
54 struct coff_link_hash_entry *, struct internal_syment *, bfd_vma *));
56 /* The NT loader points the toc register to &toc + 32768, in order to
57 use the complete range of a 16-bit displacement. We have to adjust
58 for this when we fix up loads displaced off the toc reg. */
59 #define TOC_LOAD_ADJUSTMENT (-32768)
60 #define TOC_SECTION_NAME ".private.toc"
62 /* The main body of code is in coffcode.h. */
63 #define COFF_DEFAULT_SECTION_ALIGNMENT_POWER 2
65 /* In case we're on a 32-bit machine, construct a 64-bit "-1" value
66 from smaller values. Start with zero, widen, *then* decrement. */
67 #define MINUS_ONE (((bfd_vma)0) - 1)
70 static reloc_howto_type mcore_coff_howto_table[] =
72 /* Unused: */
73 HOWTO (IMAGE_REL_MCORE_ABSOLUTE,/* type */
74 0, /* rightshift */
75 0, /* size (0 = byte, 1 = short, 2 = long) */
76 0, /* bitsize */
77 false, /* pc_relative */
78 0, /* bitpos */
79 complain_overflow_dont, /* dont complain_on_overflow */
80 NULL, /* special_function */
81 "ABSOLUTE", /* name */
82 false, /* partial_inplace */
83 0x00, /* src_mask */
84 0x00, /* dst_mask */
85 false), /* pcrel_offset */
87 HOWTO (IMAGE_REL_MCORE_ADDR32,/* type */
88 0, /* rightshift */
89 2, /* size (0 = byte, 1 = short, 2 = long) */
90 32, /* bitsize */
91 false, /* pc_relative */
92 0, /* bitpos */
93 complain_overflow_bitfield, /* complain_on_overflow */
94 NULL, /* special_function */
95 "ADDR32", /* name */
96 true, /* partial_inplace */
97 0xffffffff, /* src_mask */
98 0xffffffff, /* dst_mask */
99 false), /* pcrel_offset */
101 /* 8 bits + 2 zero bits; jmpi/jsri/lrw instructions.
102 Should not appear in object files. */
103 HOWTO (IMAGE_REL_MCORE_PCREL_IMM8BY4, /* type */
104 2, /* rightshift */
105 1, /* size (0 = byte, 1 = short, 2 = long) */
106 8, /* bitsize */
107 true, /* pc_relative */
108 0, /* bitpos */
109 complain_overflow_bitfield, /* complain_on_overflow */
110 mcore_coff_unsupported_reloc, /* special_function */
111 "IMM8BY4", /* name */
112 false, /* partial_inplace */
113 0, /* src_mask */
114 0, /* dst_mask */
115 true), /* pcrel_offset */
117 /* bsr/bt/bf/br instructions; 11 bits + 1 zero bit
118 Span 2k instructions == 4k bytes.
119 Only useful pieces at the relocated address are the opcode (5 bits) */
120 HOWTO (IMAGE_REL_MCORE_PCREL_IMM11BY2,/* type */
121 1, /* rightshift */
122 1, /* size (0 = byte, 1 = short, 2 = long) */
123 11, /* bitsize */
124 true, /* pc_relative */
125 0, /* bitpos */
126 complain_overflow_signed, /* complain_on_overflow */
127 NULL, /* special_function */
128 "IMM11BY2", /* name */
129 false, /* partial_inplace */
130 0x0, /* src_mask */
131 0x7ff, /* dst_mask */
132 true), /* pcrel_offset */
134 /* 4 bits + 1 zero bit; 'loopt' instruction only; unsupported. */
135 HOWTO (IMAGE_REL_MCORE_PCREL_IMM4BY2, /* type */
136 1, /* rightshift */
137 1, /* size (0 = byte, 1 = short, 2 = long) */
138 4, /* bitsize */
139 true, /* pc_relative */
140 0, /* bitpos */
141 complain_overflow_bitfield, /* complain_on_overflow */
142 mcore_coff_unsupported_reloc, /* special_function */
143 "IMM4BY2", /* name */
144 false, /* partial_inplace */
145 0, /* src_mask */
146 0, /* dst_mask */
147 true), /* pcrel_offset */
149 /* 32-bit pc-relative. Eventually this will help support PIC code. */
150 HOWTO (IMAGE_REL_MCORE_PCREL_32,/* type */
151 0, /* rightshift */
152 2, /* size (0 = byte, 1 = short, 2 = long) */
153 32, /* bitsize */
154 true, /* pc_relative */
155 0, /* bitpos */
156 complain_overflow_bitfield, /* complain_on_overflow */
157 NULL, /* special_function */
158 "PCREL_32", /* name */
159 false, /* partial_inplace */
160 0x0, /* src_mask */
161 0xffffffff, /* dst_mask */
162 true), /* pcrel_offset */
164 /* Like PCREL_IMM11BY2, this relocation indicates that there is a
165 'jsri' at the specified address. There is a separate relocation
166 entry for the literal pool entry that it references, but we
167 might be able to change the jsri to a bsr if the target turns out
168 to be close enough [even though we won't reclaim the literal pool
169 entry, we'll get some runtime efficiency back]. Note that this
170 is a relocation that we are allowed to safely ignore. */
171 HOWTO (IMAGE_REL_MCORE_PCREL_JSR_IMM11BY2,/* type */
172 1, /* rightshift */
173 1, /* size (0 = byte, 1 = short, 2 = long) */
174 11, /* bitsize */
175 true, /* pc_relative */
176 0, /* bitpos */
177 complain_overflow_signed, /* complain_on_overflow */
178 NULL, /* special_function */
179 "JSR_IMM11BY2", /* name */
180 false, /* partial_inplace */
181 0x0, /* src_mask */
182 0x7ff, /* dst_mask */
183 true), /* pcrel_offset */
185 HOWTO (IMAGE_REL_MCORE_RVA, /* type */
186 0, /* rightshift */
187 2, /* size (0 = byte, 1 = short, 2 = long) */
188 32, /* bitsize */
189 false, /* pc_relative */
190 0, /* bitpos */
191 complain_overflow_signed, /* complain_on_overflow */
192 NULL, /* special_function */
193 "MCORE_RVA", /* name */
194 true, /* partial_inplace */
195 0xffffffff, /* src_mask */
196 0xffffffff, /* dst_mask */
197 true) /* pcrel_offset */
200 /* Extend the coff_link_hash_table structure with a few M*Core specific fields.
201 This allows us to store global data here without actually creating any
202 global variables, which is a no-no in the BFD world. */
203 typedef struct coff_mcore_link_hash_table
205 /* The original coff_link_hash_table structure. MUST be first field. */
206 struct coff_link_hash_table root;
208 bfd * bfd_of_toc_owner;
209 long int global_toc_size;
210 long int import_table_size;
211 long int first_thunk_address;
212 long int thunk_size;
214 mcore_hash_table;
216 /* Get the MCore coff linker hash table from a link_info structure. */
217 #define coff_mcore_hash_table(info) \
218 ((mcore_hash_table *) ((info)->hash))
220 /* Create an MCore coff linker hash table. */
221 static struct bfd_link_hash_table *
222 coff_mcore_link_hash_table_create (abfd)
223 bfd * abfd;
225 mcore_hash_table * ret;
227 ret = ((mcore_hash_table *) bfd_alloc (abfd, sizeof (* ret)));
228 if (ret == (mcore_hash_table *) NULL)
229 return NULL;
231 if (! _bfd_coff_link_hash_table_init
232 (& ret->root, abfd, _bfd_coff_link_hash_newfunc))
234 bfd_release (abfd, ret);
235 return (struct bfd_link_hash_table *) NULL;
238 ret->bfd_of_toc_owner = NULL;
239 ret->global_toc_size = 0;
240 ret->import_table_size = 0;
241 ret->first_thunk_address = 0;
242 ret->thunk_size = 0;
244 return & ret->root.root;
247 /* Add an entry to the base file. */
248 static void
249 mcore_emit_base_file_entry (info, output_bfd, input_section, reloc_offset)
250 struct bfd_link_info * info;
251 bfd * output_bfd;
252 asection * input_section;
253 bfd_vma reloc_offset;
255 bfd_vma addr = reloc_offset
256 - input_section->vma
257 + input_section->output_offset
258 + input_section->output_section->vma;
260 if (coff_data (output_bfd)->pe)
261 addr -= pe_data (output_bfd)->pe_opthdr.ImageBase;
263 fwrite (&addr, 1, sizeof (addr), (FILE *) info->base_file);
266 /*ARGSUSED*/
267 static bfd_reloc_status_type
268 mcore_coff_unsupported_reloc (abfd, reloc_entry, symbol, data, input_section,
269 output_bfd, error_message)
270 bfd * abfd;
271 arelent * reloc_entry;
272 asymbol * symbol ATTRIBUTE_UNUSED;
273 PTR data ATTRIBUTE_UNUSED;
274 asection * input_section ATTRIBUTE_UNUSED;
275 bfd * output_bfd ATTRIBUTE_UNUSED;
276 char ** error_message ATTRIBUTE_UNUSED;
278 BFD_ASSERT (reloc_entry->howto != (reloc_howto_type *)0);
280 _bfd_error_handler (_("%s: Relocation %s (%d) is not currently supported.\n"),
281 bfd_get_filename (abfd),
282 reloc_entry->howto->name,
283 reloc_entry->howto->type);
285 return bfd_reloc_notsupported;
289 /* A cheesy little macro to make the code a little more readable. */
290 #define HOW2MAP(bfd_rtype, mcore_rtype) \
291 case bfd_rtype: return & mcore_coff_howto_table [mcore_rtype]
293 static reloc_howto_type *
294 mcore_coff_reloc_type_lookup (abfd, code)
295 bfd * abfd ATTRIBUTE_UNUSED;
296 bfd_reloc_code_real_type code;
298 switch (code)
300 HOW2MAP (BFD_RELOC_32, IMAGE_REL_MCORE_ADDR32);
301 HOW2MAP (BFD_RELOC_MCORE_PCREL_IMM8BY4, IMAGE_REL_MCORE_PCREL_IMM8BY4);
302 HOW2MAP (BFD_RELOC_MCORE_PCREL_IMM11BY2, IMAGE_REL_MCORE_PCREL_IMM11BY2);
303 HOW2MAP (BFD_RELOC_MCORE_PCREL_IMM4BY2, IMAGE_REL_MCORE_PCREL_IMM4BY2);
304 HOW2MAP (BFD_RELOC_32_PCREL, IMAGE_REL_MCORE_PCREL_32);
305 HOW2MAP (BFD_RELOC_MCORE_PCREL_JSR_IMM11BY2, IMAGE_REL_MCORE_PCREL_JSR_IMM11BY2);
306 HOW2MAP (BFD_RELOC_RVA, IMAGE_REL_MCORE_RVA);
307 default:
308 return NULL;
310 /*NOTREACHED*/
313 #undef HOW2MAP
315 #define RTYPE2HOWTO(cache_ptr, dst) \
316 (cache_ptr)->howto = mcore_coff_howto_table + (dst)->r_type;
318 static reloc_howto_type *
319 coff_mcore_rtype_to_howto (abfd, sec, rel, h, sym, addendp)
320 bfd * abfd ATTRIBUTE_UNUSED;
321 asection * sec;
322 struct internal_reloc * rel;
323 struct coff_link_hash_entry * h ATTRIBUTE_UNUSED;
324 struct internal_syment * sym;
325 bfd_vma * addendp;
327 reloc_howto_type * howto;
330 if (rel->r_type >= NUM_ELEM (mcore_coff_howto_table))
331 return NULL;
333 howto = mcore_coff_howto_table + rel->r_type;
335 if (rel->r_type == IMAGE_REL_MCORE_RVA)
336 * addendp -= pe_data (sec->output_section->owner)->pe_opthdr.ImageBase;
338 else if (howto->pc_relative)
340 * addendp = sec->vma - 2; /* XXX guess - is this right ? */
342 /* If the symbol is defined, then the generic code is going to
343 add back the symbol value in order to cancel out an
344 adjustment it made to the addend. However, we set the addend
345 to 0 at the start of this function. We need to adjust here,
346 to avoid the adjustment the generic code will make. FIXME:
347 This is getting a bit hackish. */
348 if (sym != NULL && sym->n_scnum != 0)
349 * addendp -= sym->n_value;
351 else
352 * addendp = 0;
354 return howto;
357 /* Return true if this relocation should appear in the output .reloc section.
358 This function is referenced in pe_mkobject in peicode.h. */
359 static boolean
360 in_reloc_p (abfd, howto)
361 bfd * abfd ATTRIBUTE_UNUSED;
362 reloc_howto_type * howto;
364 return ! howto->pc_relative && howto->type != IMAGE_REL_MCORE_RVA;
368 /* The reloc processing routine for the optimized COFF linker. */
369 static boolean
370 coff_mcore_relocate_section (output_bfd, info, input_bfd, input_section,
371 contents, relocs, syms, sections)
372 bfd * output_bfd;
373 struct bfd_link_info * info;
374 bfd * input_bfd;
375 asection * input_section;
376 bfd_byte * contents;
377 struct internal_reloc * relocs;
378 struct internal_syment * syms;
379 asection ** sections;
381 struct internal_reloc * rel;
382 struct internal_reloc * relend;
383 boolean hihalf;
384 bfd_vma hihalf_val;
386 /* If we are performing a relocateable link, we don't need to do a
387 thing. The caller will take care of adjusting the reloc
388 addresses and symbol indices. */
389 if (info->relocateable)
390 return true;
392 /* Check if we have the same endianess */
393 if ( input_bfd->xvec->byteorder != output_bfd->xvec->byteorder
394 && output_bfd->xvec->byteorder != BFD_ENDIAN_UNKNOWN)
396 (*_bfd_error_handler)
397 (_("%s: compiled for a %s endian system and target is %s endian.\n"),
398 bfd_get_filename (input_bfd),
399 bfd_big_endian (input_bfd) ? "big" : "little",
400 bfd_big_endian (output_bfd) ? "big" : "little");
402 bfd_set_error (bfd_error_wrong_format);
403 return false;
406 hihalf = false;
407 hihalf_val = 0;
409 rel = relocs;
410 relend = rel + input_section->reloc_count;
412 for (; rel < relend; rel++)
414 long symndx;
415 struct internal_syment * sym;
416 bfd_vma val;
417 bfd_vma addend;
418 bfd_reloc_status_type rstat;
419 bfd_byte * loc;
420 unsigned short r_type = rel->r_type;
421 reloc_howto_type * howto = NULL;
422 struct coff_link_hash_entry * h;
423 const char * my_name;
425 symndx = rel->r_symndx;
426 loc = contents + rel->r_vaddr - input_section->vma;
428 if (symndx == -1)
430 h = NULL;
431 sym = NULL;
433 else
435 h = obj_coff_sym_hashes (input_bfd)[symndx];
436 sym = syms + symndx;
439 addend = 0;
441 /* Get the howto and initialise the addend. */
442 howto = bfd_coff_rtype_to_howto (input_bfd, input_section, rel, h,
443 sym, & addend);
444 if (howto == NULL)
445 return false;
447 val = 0;
449 if (h == NULL)
451 if (symndx == -1)
452 my_name = "*ABS*";
453 else
455 asection * sec = sections[symndx];
457 val = (sym->n_value
458 + sec->output_section->vma
459 + sec->output_offset);
461 if (sym == NULL)
462 my_name = "*unknown*";
463 else if ( sym->_n._n_n._n_zeroes == 0
464 && sym->_n._n_n._n_offset != 0)
465 my_name = obj_coff_strings (input_bfd) + sym->_n._n_n._n_offset;
466 else
468 static char buf [SYMNMLEN + 1];
470 strncpy (buf, sym->_n._n_name, SYMNMLEN);
471 buf[SYMNMLEN] = '\0';
472 my_name = buf;
476 else
478 if ( h->root.type == bfd_link_hash_defined
479 || h->root.type == bfd_link_hash_defweak)
481 asection * sec = h->root.u.def.section;
483 val = (h->root.u.def.value
484 + sec->output_section->vma
485 + sec->output_offset);
487 else
489 if (! ((*info->callbacks->undefined_symbol)
490 (info, h->root.root.string, input_bfd, input_section,
491 rel->r_vaddr - input_section->vma, true)))
492 return false;
495 my_name = h->root.root.string;
498 rstat = bfd_reloc_ok;
500 /* Each case must do its own relocation, setting rstat appropriately. */
501 switch (r_type)
503 default:
504 _bfd_error_handler (_("%s: unsupported relocation type 0x%02x"),
505 bfd_get_filename (input_bfd), r_type);
506 bfd_set_error (bfd_error_bad_value);
507 return false;
509 case IMAGE_REL_MCORE_ABSOLUTE:
510 fprintf (stderr,
511 _("Warning: unsupported reloc %s <file %s, section %s>\n"),
512 howto->name,
513 bfd_get_filename (input_bfd),
514 input_section->name);
516 fprintf (stderr,"sym %ld (%s), r_vaddr %ld (%lx)\n",
517 rel->r_symndx, my_name, (long) rel->r_vaddr,
518 (unsigned long) rel->r_vaddr);
519 break;
521 case IMAGE_REL_MCORE_PCREL_IMM8BY4:
522 case IMAGE_REL_MCORE_PCREL_IMM11BY2:
523 case IMAGE_REL_MCORE_PCREL_IMM4BY2:
524 case IMAGE_REL_MCORE_PCREL_32:
525 case IMAGE_REL_MCORE_PCREL_JSR_IMM11BY2:
526 case IMAGE_REL_MCORE_ADDR32:
527 /* XXX fixme - shouldn't this be like the code for the RVA reloc ? */
528 rstat = _bfd_relocate_contents (howto, input_bfd, val, loc);
529 break;
531 case IMAGE_REL_MCORE_RVA:
532 rstat = _bfd_final_link_relocate
533 (howto, input_bfd,
534 input_section, contents, rel->r_vaddr - input_section->vma,
535 val, addend);
536 break;
539 if (info->base_file)
541 /* Emit a reloc if the backend thinks it needs it. */
542 if (sym && pe_data (output_bfd)->in_reloc_p (output_bfd, howto))
543 mcore_emit_base_file_entry (info, output_bfd, input_section, rel->r_vaddr);
546 switch (rstat)
548 default:
549 abort ();
551 case bfd_reloc_ok:
552 break;
554 case bfd_reloc_overflow:
555 if (! ((*info->callbacks->reloc_overflow)
556 (info, my_name, howto->name,
557 (bfd_vma) 0, input_bfd,
558 input_section, rel->r_vaddr - input_section->vma)))
559 return false;
563 return true;
567 /* Tailor coffcode.h -- macro heaven. */
569 /* We use the special COFF backend linker, with our own special touch. */
571 #define coff_bfd_reloc_type_lookup mcore_coff_reloc_type_lookup
572 #define coff_relocate_section coff_mcore_relocate_section
573 #define coff_rtype_to_howto coff_mcore_rtype_to_howto
575 #define SELECT_RELOC(internal, howto) {internal.r_type = howto->type;}
577 #define COFF_PAGE_SIZE 0x1000
579 #include "coffcode.h"
581 /* Forward declaration to initialise alterbative_target field. */
582 extern const bfd_target TARGET_LITTLE_SYM;
584 /* The transfer vectors that lead the outside world to all of the above. */
585 CREATE_BIG_COFF_TARGET_VEC (TARGET_BIG_SYM, TARGET_BIG_NAME, D_PAGED,
586 (SEC_CODE | SEC_DATA | SEC_DEBUGGING | SEC_READONLY | SEC_LINK_ONCE | SEC_LINK_DUPLICATES),
587 0, & TARGET_LITTLE_SYM)
588 CREATE_LITTLE_COFF_TARGET_VEC (TARGET_LITTLE_SYM, TARGET_LITTLE_NAME, D_PAGED,
589 (SEC_CODE | SEC_DATA | SEC_DEBUGGING | SEC_READONLY | SEC_LINK_ONCE | SEC_LINK_DUPLICATES),
590 0, & TARGET_BIG_SYM)