* targets.c (bfd_target): Rearranged fields in target vector.
[external/binutils.git] / bfd / coff-i960.c
1 /* BFD back-end for Intel 960 COFF files.
2    Copyright (C) 1990, 1991, 1992, 1993 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., 675 Mass Ave, Cambridge, MA 02139, USA.  */
20
21 #define I960 1
22 #define BADMAG(x) I960BADMAG(x)
23
24 #include "bfd.h"
25 #include "sysdep.h"
26 #include "libbfd.h"
27 #include "obstack.h"
28 #include "coff/i960.h"
29 #include "coff/internal.h"
30 #include "libcoff.h"            /* to allow easier abstraction-breaking */
31
32 static bfd_reloc_status_type optcall_callback
33   PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
34        
35 #define COFF_LONG_FILENAMES
36
37 #define CALLS    0x66003800     /* Template for 'calls' instruction     */
38 #define BAL      0x0b000000     /* Template for 'bal' instruction       */
39 #define BAL_MASK 0x00ffffff
40
41 static bfd_reloc_status_type 
42 optcall_callback (abfd, reloc_entry, symbol_in, data,
43                   ignore_input_section, ignore_bfd, error_message)
44      bfd *abfd;
45      arelent *reloc_entry;
46      asymbol *symbol_in;
47      PTR data;
48      asection *ignore_input_section;
49      bfd *ignore_bfd;
50      char **error_message;
51 {
52   /* This item has already been relocated correctly, but we may be
53    * able to patch in yet better code - done by digging out the
54    * correct info on this symbol */
55   bfd_reloc_status_type result;
56   coff_symbol_type *cs = coffsymbol(symbol_in);
57
58   /* So the target symbol has to be of coff type, and the symbol 
59      has to have the correct native information within it */
60   if ((bfd_asymbol_flavour(&cs->symbol) != bfd_target_coff_flavour)
61       || (cs->native == (combined_entry_type *)NULL))
62     {
63       /* This is interesting, consider the case where we're outputting coff
64          from a mix n match input, linking from coff to a symbol defined in a
65          bout file will cause this match to be true. Should I complain?  This
66          will only work if the bout symbol is non leaf.  */
67       *error_message =
68         (char *) "uncertain calling convention for non-COFF symbol";
69       result = bfd_reloc_dangerous;
70     }
71   else
72     {
73     switch (cs->native->u.syment.n_sclass) 
74       {
75       case C_LEAFSTAT:
76       case C_LEAFEXT:
77         /* This is a call to a leaf procedure, replace instruction with a bal
78            to the correct location.  */
79         {
80           union internal_auxent *aux = &((cs->native+2)->u.auxent);
81           int word = bfd_get_32(abfd, (bfd_byte *)data + reloc_entry->address);
82           int olf = (aux->x_bal.x_balntry - cs->native->u.syment.n_value);
83           BFD_ASSERT(cs->native->u.syment.n_numaux==2);
84
85           /* We replace the original call instruction with a bal to
86              the bal entry point - the offset of which is described in
87              the 2nd auxent of the original symbol. We keep the native
88              sym and auxents untouched, so the delta between the two
89              is the offset of the bal entry point.  */
90           word = ((word +  olf)  & BAL_MASK) | BAL;
91           bfd_put_32(abfd, word, (bfd_byte *) data + reloc_entry->address);
92         }
93         result = bfd_reloc_ok;
94         break;
95       case C_SCALL:
96         /* This is a call to a system call, replace with a calls to # */
97         BFD_ASSERT(0);
98         result = bfd_reloc_ok;
99         break;
100       default:
101         result = bfd_reloc_ok;
102         break;
103       }
104   }
105   return result;
106 }
107
108 static reloc_howto_type howto_rellong =
109   { (unsigned int) R_RELLONG, 0, 2, 32,false, 0,
110       complain_overflow_bitfield, 0,"rellong", true, 0xffffffff,
111       0xffffffff};
112 static reloc_howto_type howto_iprmed =
113   {  R_IPRMED, 0, 2, 24,true,0, complain_overflow_signed,0,
114        "iprmed ", true, 0x00ffffff, 0x00ffffff};
115 static reloc_howto_type howto_optcall =
116   {  R_OPTCALL, 0,2,24,true,0, complain_overflow_signed,
117        optcall_callback, "optcall", true, 0x00ffffff, 0x00ffffff};
118
119 static const reloc_howto_type *
120 coff_i960_reloc_type_lookup (abfd, code)
121      bfd *abfd;
122      bfd_reloc_code_real_type code;
123 {
124   switch (code)
125     {
126     default:
127       return 0;
128     case BFD_RELOC_I960_CALLJ:
129       return &howto_optcall;
130     case BFD_RELOC_32:
131       return &howto_rellong;
132     case BFD_RELOC_24_PCREL:
133       return &howto_iprmed;
134     }
135 }
136
137 /* The real code is in coffcode.h */
138
139 #define RTYPE2HOWTO(cache_ptr, dst) \
140 {                                                       \
141    reloc_howto_type *howto_ptr;                         \
142    switch ((dst)->r_type) {                             \
143      case 17: howto_ptr = &howto_rellong; break;        \
144      case 25: howto_ptr = &howto_iprmed; break;         \
145      case 27: howto_ptr = &howto_optcall; break;        \
146      default: howto_ptr = 0; break;                     \
147      }                                                  \
148    cache_ptr->howto = howto_ptr;                        \
149  }
150
151 #include "coffcode.h"
152
153 #undef coff_bfd_reloc_type_lookup
154 #define coff_bfd_reloc_type_lookup coff_i960_reloc_type_lookup
155
156 bfd_target icoff_little_vec =
157 {
158   "coff-Intel-little",          /* name */
159   bfd_target_coff_flavour,
160   false,                        /* data byte order is little */
161   false,                        /* header byte order is little */
162
163   (HAS_RELOC | EXEC_P |         /* object flags */
164    HAS_LINENO | HAS_DEBUG |
165    HAS_SYMS | HAS_LOCALS | WP_TEXT),
166
167   (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
168   0,                            /* leading underscore */
169   '/',                          /* ar_pad_char */
170   15,                           /* ar_max_namelen */
171
172   3,                            /* minimum alignment power */
173   bfd_getl64, bfd_getl_signed_64, bfd_putl64,
174      bfd_getl32, bfd_getl_signed_32, bfd_putl32,
175      bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* data */
176   bfd_getl64, bfd_getl_signed_64, bfd_putl64,
177      bfd_getl32, bfd_getl_signed_32, bfd_putl32,
178      bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* hdrs */
179
180  {_bfd_dummy_target, coff_object_p, /* bfd_check_format */
181    bfd_generic_archive_p, _bfd_dummy_target},
182  {bfd_false, coff_mkobject,     /* bfd_set_format */
183    _bfd_generic_mkarchive, bfd_false},
184  {bfd_false, coff_write_object_contents, /* bfd_write_contents */
185    _bfd_write_archive_contents, bfd_false},
186
187      BFD_JUMP_TABLE_GENERIC (coff),
188      BFD_JUMP_TABLE_COPY (coff),
189      BFD_JUMP_TABLE_CORE (_bfd_nocore),
190      BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff),
191      BFD_JUMP_TABLE_SYMBOLS (coff),
192      BFD_JUMP_TABLE_RELOCS (coff),
193      BFD_JUMP_TABLE_WRITE (coff),
194      BFD_JUMP_TABLE_LINK (coff),
195
196   COFF_SWAP_TABLE,
197 };
198
199
200 bfd_target icoff_big_vec =
201 {
202   "coff-Intel-big",             /* name */
203   bfd_target_coff_flavour,
204   false,                        /* data byte order is little */
205   true,                         /* header byte order is big */
206
207   (HAS_RELOC | EXEC_P |         /* object flags */
208    HAS_LINENO | HAS_DEBUG |
209    HAS_SYMS | HAS_LOCALS | WP_TEXT),
210
211   (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
212   0,                            /* leading underscore */
213   '/',                          /* ar_pad_char */
214   15,                           /* ar_max_namelen */
215
216   3,                            /* minimum alignment power */
217 bfd_getl64, bfd_getl_signed_64, bfd_putl64,
218      bfd_getl32, bfd_getl_signed_32, bfd_putl32,
219      bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* data */
220 bfd_getb64, bfd_getb_signed_64, bfd_putb64,
221      bfd_getb32, bfd_getb_signed_32, bfd_putb32,
222      bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* hdrs */
223
224   {_bfd_dummy_target, coff_object_p, /* bfd_check_format */
225      bfd_generic_archive_p, _bfd_dummy_target},
226   {bfd_false, coff_mkobject,    /* bfd_set_format */
227      _bfd_generic_mkarchive, bfd_false},
228   {bfd_false, coff_write_object_contents,       /* bfd_write_contents */
229      _bfd_write_archive_contents, bfd_false},
230
231      BFD_JUMP_TABLE_GENERIC (coff),
232      BFD_JUMP_TABLE_COPY (coff),
233      BFD_JUMP_TABLE_CORE (_bfd_nocore),
234      BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff),
235      BFD_JUMP_TABLE_SYMBOLS (coff),
236      BFD_JUMP_TABLE_RELOCS (coff),
237      BFD_JUMP_TABLE_WRITE (coff),
238      BFD_JUMP_TABLE_LINK (coff),
239
240   COFF_SWAP_TABLE,
241 };