xref: /openbsd/gnu/usr.bin/binutils/bfd/coff-i860.c (revision 73471bf0)
1 /* BFD back-end for Intel i860 COFF files.
2    Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1999, 2000, 2001, 2002, 2003
3    Free Software Foundation, Inc.
4    Created mostly by substituting "860" for "386" in coff-i386.c
5    Harry Dolan <dolan@ssd.intel.com>, October 1995
6 
7 This file is part of BFD, the Binary File Descriptor library.
8 
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
13 
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 GNU General Public License for more details.
18 
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
22 
23 #include "bfd.h"
24 #include "sysdep.h"
25 #include "libbfd.h"
26 
27 #include "coff/i860.h"
28 
29 #include "coff/internal.h"
30 
31 #include "libcoff.h"
32 
33 
34 #define COFF_DEFAULT_SECTION_ALIGNMENT_POWER (2)
35 /* The page size is a guess based on ELF.  */
36 
37 #define COFF_PAGE_SIZE 0x1000
38 
39 /* For some reason when using i860 COFF the value stored in the .text
40    section for a reference to a common symbol is the value itself plus
41    any desired offset.  Ian Taylor, Cygnus Support.  */
42 
43 /* If we are producing relocatable output, we need to do some
44    adjustments to the object file that are not done by the
45    bfd_perform_relocation function.  This function is called by every
46    reloc type to make any required adjustments.  */
47 
48 static bfd_reloc_status_type
49 coff_i860_reloc (bfd *abfd,
50 		 arelent *reloc_entry,
51 		 asymbol *symbol,
52 		 void *data,
53 		 asection *input_section ATTRIBUTE_UNUSED,
54 		 bfd *output_bfd,
55 		 char **error_message ATTRIBUTE_UNUSED)
56 {
57   symvalue diff;
58 
59   if (output_bfd == (bfd *) NULL)
60     return bfd_reloc_continue;
61 
62   if (bfd_is_com_section (symbol->section))
63     {
64       /* We are relocating a common symbol.  The current value in the
65 	 object file is ORIG + OFFSET, where ORIG is the value of the
66 	 common symbol as seen by the object file when it was compiled
67 	 (this may be zero if the symbol was undefined) and OFFSET is
68 	 the offset into the common symbol (normally zero, but may be
69 	 non-zero when referring to a field in a common structure).
70 	 ORIG is the negative of reloc_entry->addend, which is set by
71 	 the CALC_ADDEND macro below.  We want to replace the value in
72 	 the object file with NEW + OFFSET, where NEW is the value of
73 	 the common symbol which we are going to put in the final
74 	 object file.  NEW is symbol->value.  */
75       diff = symbol->value + reloc_entry->addend;
76     }
77   else
78     {
79       /* For some reason bfd_perform_relocation always effectively
80 	 ignores the addend for a COFF target when producing
81 	 relocatable output.  This seems to be always wrong for 860
82 	 COFF, so we handle the addend here instead.  */
83       diff = reloc_entry->addend;
84     }
85 
86 #define DOIT(x) \
87   x = ((x & ~howto->dst_mask) | (((x & howto->src_mask) + diff) & howto->dst_mask))
88 
89     if (diff != 0)
90       {
91 	reloc_howto_type *howto = reloc_entry->howto;
92 	unsigned char *addr = (unsigned char *) data + reloc_entry->address;
93 
94 	switch (howto->size)
95 	  {
96 	  case 0:
97 	    {
98 	      char x = bfd_get_8 (abfd, addr);
99 	      DOIT (x);
100 	      bfd_put_8 (abfd, x, addr);
101 	    }
102 	    break;
103 
104 	  case 1:
105 	    {
106 	      short x = bfd_get_16 (abfd, addr);
107 	      DOIT (x);
108 	      bfd_put_16 (abfd, (bfd_vma) x, addr);
109 	    }
110 	    break;
111 
112 	  case 2:
113 	    {
114 	      long x = bfd_get_32 (abfd, addr);
115 	      DOIT (x);
116 	      bfd_put_32 (abfd, (bfd_vma) x, addr);
117 	    }
118 	    break;
119 
120 	  default:
121 	    abort ();
122 	  }
123       }
124 
125   /* Now let bfd_perform_relocation finish everything up.  */
126   return bfd_reloc_continue;
127 }
128 
129 /* This is just a temporary measure until we teach bfd to generate
130    these relocations.  */
131 
132 static bfd_reloc_status_type
133 coff_i860_reloc_nyi (bfd *abfd ATTRIBUTE_UNUSED,
134 		     arelent *reloc_entry,
135 		     asymbol *symbol ATTRIBUTE_UNUSED,
136 		     void *data ATTRIBUTE_UNUSED,
137 		     asection *input_section ATTRIBUTE_UNUSED,
138 		     bfd *output_bfd ATTRIBUTE_UNUSED,
139 		     char **error_message ATTRIBUTE_UNUSED)
140 {
141   reloc_howto_type *howto = reloc_entry->howto;
142   fprintf (stderr, _("Relocation `%s' not yet implemented\n"), howto->name);
143   return bfd_reloc_notsupported;
144 }
145 
146 #ifndef PCRELOFFSET
147 #define PCRELOFFSET FALSE
148 #endif
149 
150 static reloc_howto_type howto_table[] =
151 {
152   EMPTY_HOWTO (0),
153   EMPTY_HOWTO (1),
154   EMPTY_HOWTO (2),
155   EMPTY_HOWTO (3),
156   EMPTY_HOWTO (4),
157   EMPTY_HOWTO (5),
158   HOWTO (R_DIR32,               /* type */
159 	 0,	                /* rightshift */
160 	 2,	                /* size (0 = byte, 1 = short, 2 = long) */
161 	 32,	                /* bitsize */
162 	 FALSE,	                /* pc_relative */
163 	 0,	                /* bitpos */
164 	 complain_overflow_bitfield, /* complain_on_overflow */
165 	 coff_i860_reloc,       /* special_function */
166 	 "dir32",               /* name */
167 	 TRUE,	                /* partial_inplace */
168 	 0xffffffff,            /* src_mask */
169 	 0xffffffff,            /* dst_mask */
170 	 TRUE),                /* pcrel_offset */
171   /* {7}, */
172   HOWTO (R_IMAGEBASE,            /* type */
173 	 0,	                /* rightshift */
174 	 2,	                /* size (0 = byte, 1 = short, 2 = long) */
175 	 32,	                /* bitsize */
176 	 FALSE,	                /* pc_relative */
177 	 0,	                /* bitpos */
178 	 complain_overflow_bitfield, /* complain_on_overflow */
179 	 coff_i860_reloc,       /* special_function */
180 	 "rva32",	           /* name */
181 	 TRUE,	                /* partial_inplace */
182 	 0xffffffff,            /* src_mask */
183 	 0xffffffff,            /* dst_mask */
184 	 FALSE),                /* pcrel_offset */
185   EMPTY_HOWTO (010),
186   EMPTY_HOWTO (011),
187   EMPTY_HOWTO (012),
188   EMPTY_HOWTO (013),
189   EMPTY_HOWTO (014),
190   EMPTY_HOWTO (015),
191   EMPTY_HOWTO (016),
192   HOWTO (R_RELBYTE,		/* type */
193 	 0,			/* rightshift */
194 	 0,			/* size (0 = byte, 1 = short, 2 = long) */
195 	 8,			/* bitsize */
196 	 FALSE,			/* pc_relative */
197 	 0,			/* bitpos */
198 	 complain_overflow_bitfield, /* complain_on_overflow */
199 	 coff_i860_reloc,	/* special_function */
200 	 "8",			/* name */
201 	 TRUE,			/* partial_inplace */
202 	 0x000000ff,		/* src_mask */
203 	 0x000000ff,		/* dst_mask */
204 	 PCRELOFFSET),		/* pcrel_offset */
205   HOWTO (R_RELWORD,		/* type */
206 	 0,			/* rightshift */
207 	 1,			/* size (0 = byte, 1 = short, 2 = long) */
208 	 16,			/* bitsize */
209 	 FALSE,			/* pc_relative */
210 	 0,			/* bitpos */
211 	 complain_overflow_bitfield, /* complain_on_overflow */
212 	 coff_i860_reloc,	/* special_function */
213 	 "16",			/* name */
214 	 TRUE,			/* partial_inplace */
215 	 0x0000ffff,		/* src_mask */
216 	 0x0000ffff,		/* dst_mask */
217 	 PCRELOFFSET),		/* pcrel_offset */
218   HOWTO (R_RELLONG,		/* type */
219 	 0,			/* rightshift */
220 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
221 	 32,			/* bitsize */
222 	 FALSE,			/* pc_relative */
223 	 0,			/* bitpos */
224 	 complain_overflow_bitfield, /* complain_on_overflow */
225 	 coff_i860_reloc,	/* special_function */
226 	 "32",			/* name */
227 	 TRUE,			/* partial_inplace */
228 	 0xffffffff,		/* src_mask */
229 	 0xffffffff,		/* dst_mask */
230 	 PCRELOFFSET),		/* pcrel_offset */
231   HOWTO (R_PCRBYTE,		/* type */
232 	 0,			/* rightshift */
233 	 0,			/* size (0 = byte, 1 = short, 2 = long) */
234 	 8,			/* bitsize */
235 	 TRUE,			/* pc_relative */
236 	 0,			/* bitpos */
237 	 complain_overflow_signed, /* complain_on_overflow */
238 	 coff_i860_reloc,	/* special_function */
239 	 "DISP8",		/* name */
240 	 TRUE,			/* partial_inplace */
241 	 0x000000ff,		/* src_mask */
242 	 0x000000ff,		/* dst_mask */
243 	 PCRELOFFSET),		/* pcrel_offset */
244   HOWTO (R_PCRWORD,		/* type */
245 	 0,			/* rightshift */
246 	 1,			/* size (0 = byte, 1 = short, 2 = long) */
247 	 16,			/* bitsize */
248 	 TRUE,			/* pc_relative */
249 	 0,			/* bitpos */
250 	 complain_overflow_signed, /* complain_on_overflow */
251 	 coff_i860_reloc,	/* special_function */
252 	 "DISP16",		/* name */
253 	 TRUE,			/* partial_inplace */
254 	 0x0000ffff,		/* src_mask */
255 	 0x0000ffff,		/* dst_mask */
256 	 PCRELOFFSET),		/* pcrel_offset */
257   HOWTO (R_PCRLONG,		/* type */
258 	 0,			/* rightshift */
259 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
260 	 32,			/* bitsize */
261 	 TRUE,			/* pc_relative */
262 	 0,			/* bitpos */
263 	 complain_overflow_signed, /* complain_on_overflow */
264 	 coff_i860_reloc,	/* special_function */
265 	 "DISP32",		/* name */
266 	 TRUE,			/* partial_inplace */
267 	 0xffffffff,		/* src_mask */
268 	 0xffffffff,		/* dst_mask */
269 	 PCRELOFFSET),		/* pcrel_offset */
270   EMPTY_HOWTO (0x15),
271   EMPTY_HOWTO (0x16),
272   EMPTY_HOWTO (0x17),
273   EMPTY_HOWTO (0x18),
274   EMPTY_HOWTO (0x19),
275   EMPTY_HOWTO (0x1a),
276   EMPTY_HOWTO (0x1b),
277   HOWTO (COFF860_R_PAIR,	/* type */
278 	 0,			/* rightshift */
279 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
280 	 16,			/* bitsize */
281 	 FALSE,			/* pc_relative */
282 	 0,			/* bitpos */
283 	 complain_overflow_dont, /* complain_on_overflow */
284 	 coff_i860_reloc_nyi,	/* special_function */
285 	 "PAIR",		/* name */
286 	 FALSE,			/* partial_inplace */
287 	 0xffff,		/* src_mask */
288 	 0xffff,		/* dst_mask */
289 	 FALSE),	        /* pcrel_offset */
290   EMPTY_HOWTO (0x1d),
291   HOWTO (COFF860_R_HIGH,	/* type */
292 	 16,			/* rightshift */
293 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
294 	 16,			/* bitsize */
295 	 FALSE,			/* pc_relative */
296 	 0,			/* bitpos */
297 	 complain_overflow_dont, /* complain_on_overflow */
298 	 coff_i860_reloc,	/* special_function */
299 	 "HIGH",		/* name */
300 	 FALSE,			/* partial_inplace */
301 	 0xffff,		/* src_mask */
302 	 0xffff,		/* dst_mask */
303 	 FALSE),	        /* pcrel_offset */
304   HOWTO (COFF860_R_LOW0,        /* type */
305 	 0,			/* rightshift */
306 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
307 	 16,			/* bitsize */
308 	 FALSE,			/* pc_relative */
309 	 0,			/* bitpos */
310 	 complain_overflow_dont, /* complain_on_overflow */
311 	 coff_i860_reloc,	/* special_function */
312 	 "LOW0",		/* name */
313 	 FALSE,			/* partial_inplace */
314 	 0xffff,		/* src_mask */
315 	 0xffff,		/* dst_mask */
316 	 FALSE),	        /* pcrel_offset */
317   HOWTO (COFF860_R_LOW1,        /* type */
318 	 0,			/* rightshift */
319 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
320 	 16,			/* bitsize */
321 	 FALSE,			/* pc_relative */
322 	 0,			/* bitpos */
323 	 complain_overflow_dont, /* complain_on_overflow */
324 	 coff_i860_reloc,	/* special_function */
325 	 "LOW1",		/* name */
326 	 FALSE,			/* partial_inplace */
327 	 0xfffe,		/* src_mask */
328 	 0xfffe,		/* dst_mask */
329 	 FALSE),	        /* pcrel_offset */
330   HOWTO (COFF860_R_LOW2,        /* type */
331 	 0,			/* rightshift */
332 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
333 	 16,			/* bitsize */
334 	 FALSE,			/* pc_relative */
335 	 0,			/* bitpos */
336 	 complain_overflow_dont, /* complain_on_overflow */
337 	 coff_i860_reloc,	/* special_function */
338 	 "LOW2",		/* name */
339 	 FALSE,			/* partial_inplace */
340 	 0xfffc,		/* src_mask */
341 	 0xfffc,		/* dst_mask */
342 	 FALSE),	        /* pcrel_offset */
343   HOWTO (COFF860_R_LOW3,        /* type */
344 	 0,			/* rightshift */
345 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
346 	 16,			/* bitsize */
347 	 FALSE,			/* pc_relative */
348 	 0,			/* bitpos */
349 	 complain_overflow_dont, /* complain_on_overflow */
350 	 coff_i860_reloc,	/* special_function */
351 	 "LOW3",		/* name */
352 	 FALSE,			/* partial_inplace */
353 	 0xfff8,		/* src_mask */
354 	 0xfff8,		/* dst_mask */
355 	 FALSE),	        /* pcrel_offset */
356   HOWTO (COFF860_R_LOW4,        /* type */
357 	 0,			/* rightshift */
358 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
359 	 16,			/* bitsize */
360 	 FALSE,			/* pc_relative */
361 	 0,			/* bitpos */
362 	 complain_overflow_dont, /* complain_on_overflow */
363 	 coff_i860_reloc,	/* special_function */
364 	 "LOW4",		/* name */
365 	 FALSE,			/* partial_inplace */
366 	 0xfff0,		/* src_mask */
367 	 0xfff0,		/* dst_mask */
368 	 FALSE),	        /* pcrel_offset */
369   HOWTO (COFF860_R_SPLIT0,      /* type */
370 	 0,			/* rightshift */
371 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
372 	 16,			/* bitsize */
373 	 FALSE,			/* pc_relative */
374 	 0,			/* bitpos */
375 	 complain_overflow_dont, /* complain_on_overflow */
376 	 coff_i860_reloc_nyi,	/* special_function */
377 	 "SPLIT0",		/* name */
378 	 FALSE,			/* partial_inplace */
379 	 0x1f07ff,		/* src_mask */
380 	 0x1f07ff,		/* dst_mask */
381 	 FALSE),	        /* pcrel_offset */
382   HOWTO (COFF860_R_SPLIT1,      /* type */
383 	 0,			/* rightshift */
384 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
385 	 16,			/* bitsize */
386 	 FALSE,			/* pc_relative */
387 	 0,			/* bitpos */
388 	 complain_overflow_dont, /* complain_on_overflow */
389 	 coff_i860_reloc_nyi,	/* special_function */
390 	 "SPLIT1",		/* name */
391 	 FALSE,			/* partial_inplace */
392 	 0x1f07fe,		/* src_mask */
393 	 0x1f07fe,		/* dst_mask */
394 	 FALSE),	        /* pcrel_offset */
395   HOWTO (COFF860_R_SPLIT2,      /* type */
396 	 0,			/* rightshift */
397 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
398 	 16,			/* bitsize */
399 	 FALSE,			/* pc_relative */
400 	 0,			/* bitpos */
401 	 complain_overflow_dont, /* complain_on_overflow */
402 	 coff_i860_reloc_nyi,	/* special_function */
403 	 "SPLIT2",		/* name */
404 	 FALSE,			/* partial_inplace */
405 	 0x1f07fc,		/* src_mask */
406 	 0x1f07fc,		/* dst_mask */
407 	 FALSE),	        /* pcrel_offset */
408   HOWTO (COFF860_R_HIGHADJ,     /* type */
409 	 0,			/* rightshift */
410 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
411 	 16,			/* bitsize */
412 	 FALSE,			/* pc_relative */
413 	 0,			/* bitpos */
414 	 complain_overflow_dont, /* complain_on_overflow */
415 	 coff_i860_reloc_nyi,	/* special_function */
416 	 "HIGHADJ",		/* name */
417 	 FALSE,			/* partial_inplace */
418 	 0xffff,		/* src_mask */
419 	 0xffff,		/* dst_mask */
420 	 FALSE),	        /* pcrel_offset */
421   HOWTO (COFF860_R_BRADDR,      /* type */
422 	 2,			/* rightshift */
423 	 2,			/* size (0 = byte, 1 = short, 2 = long) */
424 	 26,			/* bitsize */
425 	 TRUE,			/* pc_relative */
426 	 0,			/* bitpos */
427 	 complain_overflow_bitfield, /* complain_on_overflow */
428 	 coff_i860_reloc_nyi,	/* special_function */
429 	 "BRADDR",		/* name */
430 	 FALSE,			/* partial_inplace */
431 	 0x3ffffff,		/* src_mask */
432 	 0x3ffffff,		/* dst_mask */
433 	 TRUE)		        /* pcrel_offset */
434 };
435 
436 /* Turn a howto into a reloc number.  */
437 
438 #define SELECT_RELOC(x,howto) { x.r_type = howto->type; }
439 #define BADMAG(x) I860BADMAG(x)
440 #define I860 1			/* Customize coffcode.h */
441 
442 #define RTYPE2HOWTO(cache_ptr, dst)					\
443   ((cache_ptr)->howto =							\
444    ((dst)->r_type < sizeof (howto_table) / sizeof (howto_table[0])	\
445     ? howto_table + (dst)->r_type					\
446     : NULL))
447 
448 /* For 860 COFF a STYP_NOLOAD | STYP_BSS section is part of a shared
449    library.  On some other COFF targets STYP_BSS is normally
450    STYP_NOLOAD.  */
451 #define BSS_NOLOAD_IS_SHARED_LIBRARY
452 
453 /* Compute the addend of a reloc.  If the reloc is to a common symbol,
454    the object file contains the value of the common symbol.  By the
455    time this is called, the linker may be using a different symbol
456    from a different object file with a different value.  Therefore, we
457    hack wildly to locate the original symbol from this file so that we
458    can make the correct adjustment.  This macro sets coffsym to the
459    symbol from the original file, and uses it to set the addend value
460    correctly.  If this is not a common symbol, the usual addend
461    calculation is done, except that an additional tweak is needed for
462    PC relative relocs.
463    FIXME: This macro refers to symbols and asect; these are from the
464    calling function, not the macro arguments.  */
465 
466 /* FIXME: This was copied from the i386 version originally but
467    appears to be wrong for i860.  For now we'll do nothing.  */
468 #if 0
469 #define CALC_ADDEND(abfd, ptr, reloc, cache_ptr)		\
470   {								\
471     coff_symbol_type *coffsym = (coff_symbol_type *) NULL;	\
472     if (ptr && bfd_asymbol_bfd (ptr) != abfd)			\
473       coffsym = (obj_symbols (abfd)				\
474 	         + (cache_ptr->sym_ptr_ptr - symbols));		\
475     else if (ptr)						\
476       coffsym = coff_symbol_from (abfd, ptr);			\
477     if (coffsym != (coff_symbol_type *) NULL			\
478 	&& coffsym->native->u.syment.n_scnum == 0)		\
479       cache_ptr->addend = - coffsym->native->u.syment.n_value;	\
480     else if (ptr && bfd_asymbol_bfd (ptr) == abfd		\
481 	     && ptr->section != (asection *) NULL)		\
482       cache_ptr->addend = - (ptr->section->vma + ptr->value);	\
483     else							\
484       cache_ptr->addend = 0;					\
485     if (ptr && howto_table[reloc.r_type].pc_relative)		\
486       cache_ptr->addend += asect->vma;				\
487   }
488 #else
489 #define CALC_ADDEND(abfd, ptr, reloc, cache_ptr)
490 #endif
491 
492 /* We use the special COFF backend linker.  */
493 #define coff_relocate_section _bfd_coff_generic_relocate_section
494 
495 static reloc_howto_type *
496 coff_i860_rtype_to_howto (bfd *abfd ATTRIBUTE_UNUSED,
497 			  asection *sec,
498 			  struct internal_reloc *rel,
499 			  struct coff_link_hash_entry *h,
500 			  struct internal_syment *sym,
501 			  bfd_vma *addendp)
502 {
503 
504   reloc_howto_type *howto;
505 
506   if (rel->r_type > sizeof (howto_table) / sizeof (howto_table[0]))
507     {
508       bfd_set_error (bfd_error_bad_value);
509       return NULL;
510     }
511 
512   howto = howto_table + rel->r_type;
513 
514   if (howto->pc_relative)
515     *addendp += sec->vma;
516 
517   if (sym != NULL && sym->n_scnum == 0 && sym->n_value != 0)
518     {
519       /* This is a common symbol.  The section contents include the
520 	 size (sym->n_value) as an addend.  The relocate_section
521 	 function will be adding in the final value of the symbol.  We
522 	 need to subtract out the current size in order to get the
523 	 correct result.  */
524 
525       BFD_ASSERT (h != NULL);
526 
527       /* I think we *do* want to bypass this.  If we don't, I have seen some data
528 	 parameters get the wrong relocation address.  If I link two versions
529 	 with and without this section bypassed and then do a binary comparison,
530 	 the addresses which are different can be looked up in the map.  The
531 	 case in which this section has been bypassed has addresses which correspond
532 	 to values I can find in the map.  */
533       *addendp -= sym->n_value;
534     }
535 
536   /* If the output symbol is common (in which case this must be a
537      relocatable link), we need to add in the final size of the
538      common symbol.  */
539   if (h != NULL && h->root.type == bfd_link_hash_common)
540     *addendp += h->root.u.c.size;
541 
542   return howto;
543 }
544 
545 static reloc_howto_type *
546 coff_i860_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
547 			     bfd_reloc_code_real_type code)
548 {
549   switch (code)
550     {
551     case BFD_RELOC_32:
552       return howto_table + R_DIR32;
553     case BFD_RELOC_860_PC26:
554       return howto_table + COFF860_R_BRADDR;
555     case BFD_RELOC_860_PC16:
556       /* ??? How to handle PC16 for COFF?  SPLIT0 is close for now.  */
557       return howto_table + COFF860_R_SPLIT0;
558     case BFD_RELOC_860_LOW0:
559       return howto_table + COFF860_R_LOW0;
560     case BFD_RELOC_860_SPLIT0:
561       return howto_table + COFF860_R_SPLIT0;
562     case BFD_RELOC_860_LOW1:
563       return howto_table + COFF860_R_LOW1;
564     case BFD_RELOC_860_SPLIT1:
565       return howto_table + COFF860_R_SPLIT1;
566     case BFD_RELOC_860_LOW2:
567       return howto_table + COFF860_R_LOW2;
568     case BFD_RELOC_860_SPLIT2:
569       return howto_table + COFF860_R_SPLIT2;
570     case BFD_RELOC_860_LOW3:
571       return howto_table + COFF860_R_LOW3;
572     case BFD_RELOC_860_HIGHADJ:
573       return howto_table + COFF860_R_HIGHADJ;
574     case BFD_RELOC_860_HIGH:
575       return howto_table + COFF860_R_HIGH;
576     default:
577       BFD_FAIL ();
578       return 0;
579     }
580 }
581 
582 /* This is called from coff_slurp_reloc_table for each relocation
583    entry.  This special handling is due to the `PAIR' relocation
584    which has a different meaning for the `r_symndx' field.  */
585 
586 static void
587 i860_reloc_processing (arelent *cache_ptr, struct internal_reloc *dst,
588 		       asymbol **symbols, bfd *abfd, asection *asect)
589 {
590   if (dst->r_type == COFF860_R_PAIR)
591     {
592       /* Handle the PAIR relocation specially.  */
593       cache_ptr->howto = howto_table + dst->r_type;
594       cache_ptr->address = dst->r_vaddr;
595       cache_ptr->addend = dst->r_symndx;
596       cache_ptr->sym_ptr_ptr= bfd_abs_section_ptr->symbol_ptr_ptr;
597     }
598   else
599     {
600       /* For every other relocation, do exactly what coff_slurp_reloc_table
601          would do (which this code is taken directly from).  */
602       asymbol *ptr = NULL;
603       cache_ptr->address = dst->r_vaddr;
604 
605       if (dst->r_symndx != -1)
606 	{
607 	  if (dst->r_symndx < 0 || dst->r_symndx >= obj_conv_table_size (abfd))
608 	    {
609 	      (*_bfd_error_handler)
610 		(_("%s: warning: illegal symbol index %ld in relocs"),
611 		 bfd_archive_filename (abfd), dst->r_symndx);
612 	      cache_ptr->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
613 	      ptr = NULL;
614 	    }
615 	  else
616 	    {
617 	      cache_ptr->sym_ptr_ptr = (symbols
618 					+ obj_convert (abfd)[dst->r_symndx]);
619 	      ptr = *(cache_ptr->sym_ptr_ptr);
620 	    }
621 	}
622       else
623 	{
624 	  cache_ptr->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
625 	  ptr = NULL;
626 	}
627 
628       /* The symbols definitions that we have read in have been
629 	 relocated as if their sections started at 0. But the offsets
630 	 refering to the symbols in the raw data have not been
631 	 modified, so we have to have a negative addend to compensate.
632 
633 	 Note that symbols which used to be common must be left alone.  */
634 
635       /* Calculate any reloc addend by looking at the symbol.  */
636       CALC_ADDEND (abfd, ptr, (*dst), cache_ptr);
637 
638       cache_ptr->address -= asect->vma;
639 
640       /* Fill in the cache_ptr->howto field from dst->r_type.  */
641       RTYPE2HOWTO (cache_ptr, dst);
642     }
643 }
644 
645 #define coff_rtype_to_howto		coff_i860_rtype_to_howto
646 #define coff_bfd_reloc_type_lookup	coff_i860_reloc_type_lookup
647 
648 #define RELOC_PROCESSING(relent, reloc, symbols, abfd, section) \
649   i860_reloc_processing (relent, reloc, symbols, abfd, section)
650 
651 #include "coffcode.h"
652 
653 static const bfd_target *
654 i3coff_object_p(bfd *a)
655 {
656   return coff_object_p (a);
657 }
658 
659 const bfd_target
660 #ifdef TARGET_SYM
661   TARGET_SYM =
662 #else
663   i860coff_vec =
664 #endif
665 {
666 #ifdef TARGET_NAME
667   TARGET_NAME,
668 #else
669   "coff-i860",			/* name */
670 #endif
671   bfd_target_coff_flavour,
672   BFD_ENDIAN_LITTLE,		/* data byte order is little */
673   BFD_ENDIAN_LITTLE,		/* header byte order is little */
674 
675   (HAS_RELOC | EXEC_P |		/* object flags */
676    HAS_LINENO | HAS_DEBUG |
677    HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
678 
679   (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
680   '_',				/* leading underscore */
681   '/',				/* ar_pad_char */
682   15,				/* ar_max_namelen */
683 
684   bfd_getl64, bfd_getl_signed_64, bfd_putl64,
685      bfd_getl32, bfd_getl_signed_32, bfd_putl32,
686      bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* data */
687   bfd_getl64, bfd_getl_signed_64, bfd_putl64,
688      bfd_getl32, bfd_getl_signed_32, bfd_putl32,
689      bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* hdrs */
690 
691 /* Note that we allow an object file to be treated as a core file as well.  */
692     {_bfd_dummy_target, i3coff_object_p, /* bfd_check_format */
693        bfd_generic_archive_p, i3coff_object_p},
694     {bfd_false, coff_mkobject, _bfd_generic_mkarchive, /* bfd_set_format */
695        bfd_false},
696     {bfd_false, coff_write_object_contents, /* bfd_write_contents */
697        _bfd_write_archive_contents, bfd_false},
698 
699      BFD_JUMP_TABLE_GENERIC (coff),
700      BFD_JUMP_TABLE_COPY (coff),
701      BFD_JUMP_TABLE_CORE (_bfd_nocore),
702      BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff),
703      BFD_JUMP_TABLE_SYMBOLS (coff),
704      BFD_JUMP_TABLE_RELOCS (coff),
705      BFD_JUMP_TABLE_WRITE (coff),
706      BFD_JUMP_TABLE_LINK (coff),
707      BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
708 
709   NULL,
710 
711   COFF_SWAP_TABLE
712 };
713