This commit was generated by cvs2svn to track changes on a CVS vendor
[external/binutils.git] / bfd / coff-m88k.c
1 /* BFD back-end for Motorola 88000 COFF "Binary Compatability Standard" files.
2    Copyright 1990, 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
3    Written by Cygnus Support.
4
5 This file is part of BFD, the Binary File Descriptor library.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
20
21 #define M88 1           /* Customize various include files */
22 #include "bfd.h"
23 #include "sysdep.h"
24 #include "libbfd.h"
25 #include "obstack.h"
26 #include "coff/m88k.h"
27 #include "coff/internal.h"
28 #include "libcoff.h"
29
30 static bfd_reloc_status_type m88k_special_reloc
31   PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
32 static void rtype2howto PARAMS ((arelent *, struct internal_reloc *));
33 static void reloc_processing
34   PARAMS ((arelent *, struct internal_reloc *, asymbol **, bfd *, asection *));
35
36 #define COFF_DEFAULT_SECTION_ALIGNMENT_POWER (3)
37
38 static bfd_reloc_status_type 
39 m88k_special_reloc (abfd, reloc_entry, symbol, data,
40                     input_section, output_bfd, error_message)
41      bfd *abfd;
42      arelent *reloc_entry;
43      asymbol *symbol;
44      PTR data;
45      asection *input_section;
46      bfd *output_bfd;
47      char **error_message;
48 {
49   reloc_howto_type *howto = reloc_entry->howto;
50
51   switch (howto->type)
52     {
53     case R_HVRT16:
54     case R_LVRT16:
55       if (output_bfd != (bfd *) NULL)
56         {
57           /* This is a partial relocation, and we want to apply the
58              relocation to the reloc entry rather than the raw data.
59              Modify the reloc inplace to reflect what we now know.  */
60
61           reloc_entry->address += input_section->output_offset;
62         }
63       else
64         {
65           bfd_vma output_base = 0;
66           bfd_vma addr = reloc_entry->address;
67           bfd_vma x = bfd_get_16 (abfd, (bfd_byte *) data + addr);
68           asection *reloc_target_output_section;
69           long relocation = 0;
70
71           /* Work out which section the relocation is targetted at and the
72              initial relocation command value.  */
73
74           /* Get symbol value.  (Common symbols are special.)  */
75           if (bfd_is_com_section (symbol->section))
76             relocation = 0;
77           else
78             relocation = symbol->value;
79
80           reloc_target_output_section = symbol->section->output_section;
81
82           /* Convert input-section-relative symbol value to absolute.  */
83           if (output_bfd)
84             output_base = 0;
85           else
86             output_base = reloc_target_output_section->vma;
87
88           relocation += output_base + symbol->section->output_offset;
89
90           /* Add in supplied addend.  */
91           relocation += ((reloc_entry->addend << howto->bitsize) + x);
92
93           reloc_entry->addend = 0;
94
95           relocation >>= (bfd_vma) howto->rightshift;
96
97           /* Shift everything up to where it's going to be used */
98
99           relocation <<= (bfd_vma) howto->bitpos;
100
101           if (relocation)
102               bfd_put_16 (abfd, relocation, (unsigned char *) data + addr);
103         }
104
105       return bfd_reloc_ok;
106       break;
107
108     default:
109       if (output_bfd != (bfd *) NULL)
110         {
111           /* This is a partial relocation, and we want to apply the
112              relocation to the reloc entry rather than the raw data.
113              Modify the reloc inplace to reflect what we now know.  */
114
115           reloc_entry->address += input_section->output_offset;
116           return bfd_reloc_ok;
117         }
118       break;
119     }
120
121   if (output_bfd == (bfd *) NULL)
122     return bfd_reloc_continue;
123
124   return bfd_reloc_ok;
125 }
126
127 static reloc_howto_type howto_table[] = 
128 {
129   HOWTO (R_PCR16L,                      /* type */
130          02,                            /* rightshift */
131          1,                             /* size (0 = byte, 1 = short, 2 = long) */
132          16,                            /* bitsize */
133          true,                          /* pc_relative */
134          0,                             /* bitpos */
135          complain_overflow_signed,      /* complain_on_overflow */
136          m88k_special_reloc,            /* special_function */
137          "PCR16L",                      /* name */
138          false,                         /* partial_inplace */
139          0x0000ffff,                    /* src_mask */
140          0x0000ffff,                    /* dst_mask */
141          true),                         /* pcrel_offset */
142
143   HOWTO (R_PCR26L,                      /* type */
144          02,                            /* rightshift */
145          2,                             /* size (0 = byte, 1 = short, 2 = long) */
146          26,                            /* bitsize */
147          true,                          /* pc_relative */
148          0,                             /* bitpos */
149          complain_overflow_signed,      /* complain_on_overflow */
150          m88k_special_reloc,            /* special_function */
151          "PCR26L",                      /* name */
152          false,                         /* partial_inplace */
153          0x03ffffff,                    /* src_mask */
154          0x03ffffff,                    /* dst_mask */
155          true),                         /* pcrel_offset */
156
157   HOWTO (R_VRT16,                       /* type */
158          00,                            /* rightshift */
159          1,                             /* size (0 = byte, 1 = short, 2 = long) */
160          16,                            /* bitsize */
161          false,                         /* pc_relative */
162          0,                             /* bitpos */
163          complain_overflow_bitfield,    /* complain_on_overflow */
164          m88k_special_reloc,            /* special_function */
165          "VRT16",                       /* name */
166          false,                         /* partial_inplace */
167          0x0000ffff,                    /* src_mask */
168          0x0000ffff,                    /* dst_mask */
169          true),                         /* pcrel_offset */
170
171   HOWTO (R_HVRT16,                      /* type */
172          16,                            /* rightshift */
173          1,                             /* size (0 = byte, 1 = short, 2 = long) */
174          16,                            /* bitsize */
175          false,                         /* pc_relative */
176          0,                             /* bitpos */
177          complain_overflow_dont,        /* complain_on_overflow */
178          m88k_special_reloc,            /* special_function */
179          "HVRT16",                      /* name */
180          false,                         /* partial_inplace */
181          0x0000ffff,                    /* src_mask */
182          0x0000ffff,                    /* dst_mask */
183          true),                         /* pcrel_offset */
184
185   HOWTO (R_LVRT16,                      /* type */
186          00,                            /* rightshift */
187          1,                             /* size (0 = byte, 1 = short, 2 = long) */
188          16,                            /* bitsize */
189          false,                         /* pc_relative */
190          0,                             /* bitpos */
191          complain_overflow_dont,        /* complain_on_overflow */
192          m88k_special_reloc,            /* special_function */
193          "LVRT16",                      /* name */
194          false,                         /* partial_inplace */
195          0x0000ffff,                    /* src_mask */
196          0x0000ffff,                    /* dst_mask */
197          true),                         /* pcrel_offset */
198
199   HOWTO (R_VRT32,                       /* type */
200          00,                            /* rightshift */
201          2,                             /* size (0 = byte, 1 = short, 2 = long) */
202          32,                            /* bitsize */
203          false,                         /* pc_relative */
204          0,                             /* bitpos */
205          complain_overflow_bitfield,    /* complain_on_overflow */
206          m88k_special_reloc,            /* special_function */
207          "VRT32",                       /* name */
208          false,                         /* partial_inplace */
209          0xffffffff,                    /* src_mask */
210          0xffffffff,                    /* dst_mask */
211          true),                         /* pcrel_offset */
212 };
213
214 /* Code to turn an external r_type into a pointer to an entry in the
215    above howto table.  */
216 static void
217 rtype2howto (cache_ptr, dst)
218      arelent *cache_ptr;
219      struct internal_reloc *dst;
220 {
221   if (dst->r_type >= R_PCR16L && dst->r_type <= R_VRT32)
222     {
223       cache_ptr->howto = howto_table + dst->r_type - R_PCR16L;
224     }
225   else
226     {
227       BFD_ASSERT (0);
228     }
229 }
230
231 #define RTYPE2HOWTO(cache_ptr, dst) rtype2howto (cache_ptr, dst)
232
233
234 /* Code to swap in the reloc offset */
235 #define SWAP_IN_RELOC_OFFSET  bfd_h_get_16
236 #define SWAP_OUT_RELOC_OFFSET bfd_h_put_16
237
238
239 #define RELOC_PROCESSING(relent,reloc,symbols,abfd,section)     \
240   reloc_processing(relent, reloc, symbols, abfd, section)
241
242 static void
243 reloc_processing (relent, reloc, symbols, abfd, section)
244      arelent *relent;
245      struct internal_reloc *reloc;
246      asymbol **symbols;
247      bfd *abfd;
248      asection *section;
249 {
250   relent->address = reloc->r_vaddr;
251   rtype2howto (relent, reloc);
252
253   if (((int) reloc->r_symndx) > 0)
254     {
255       relent->sym_ptr_ptr = symbols + obj_convert (abfd)[reloc->r_symndx];
256     }
257   else
258     {
259       relent->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
260     }
261
262   relent->addend = reloc->r_offset;
263   relent->address -= section->vma;
264 }
265
266 #define BADMAG(x) MC88BADMAG(x)
267 #include "coffcode.h"
268
269 #undef coff_write_armap
270
271 const bfd_target m88kbcs_vec =
272 {
273   "coff-m88kbcs",               /* name */
274   bfd_target_coff_flavour,
275   true,                         /* data byte order is big */
276   true,                         /* header byte order is big */
277
278   (HAS_RELOC | EXEC_P |         /* object flags */
279    HAS_LINENO | HAS_DEBUG |
280    HAS_SYMS | HAS_LOCALS | WP_TEXT),
281
282   (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
283   '_',                          /* leading underscore */
284   '/',                          /* ar_pad_char */
285   15,                           /* ar_max_namelen */
286   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
287      bfd_getb32, bfd_getb_signed_32, bfd_putb32,
288      bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* data */
289   bfd_getb64, bfd_getb_signed_64, bfd_putb64,
290      bfd_getb32, bfd_getb_signed_32, bfd_putb32,
291      bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* hdrs */
292
293     {_bfd_dummy_target, coff_object_p, /* bfd_check_format */
294        bfd_generic_archive_p, _bfd_dummy_target},
295     {bfd_false, coff_mkobject, _bfd_generic_mkarchive, /* bfd_set_format */
296        bfd_false},
297     {bfd_false, coff_write_object_contents, /* bfd_write_contents */
298        _bfd_write_archive_contents, bfd_false},
299
300      BFD_JUMP_TABLE_GENERIC (coff),
301      BFD_JUMP_TABLE_COPY (coff),
302      BFD_JUMP_TABLE_CORE (_bfd_nocore),
303      BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff),
304      BFD_JUMP_TABLE_SYMBOLS (coff),
305      BFD_JUMP_TABLE_RELOCS (coff),
306      BFD_JUMP_TABLE_WRITE (coff),
307      BFD_JUMP_TABLE_LINK (coff),
308      BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
309
310   COFF_SWAP_TABLE,
311 };