(howto_rellong, howto_iprmed, howto_optcall): Use HOWTO macro.
[platform/upstream/binutils.git] / bfd / coff-i960.c
1 /* BFD back-end for Intel 960 COFF files.
2    Copyright (C) 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., 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   HOWTO ((unsigned int) R_RELLONG, 0, 2, 32,false, 0,
110          complain_overflow_bitfield, 0,"rellong", true, 0xffffffff,
111          0xffffffff, 0);
112 static reloc_howto_type howto_iprmed =
113   HOWTO (R_IPRMED, 0, 2, 24,true,0, complain_overflow_signed,0,
114          "iprmed ", true, 0x00ffffff, 0x00ffffff, 0);
115 static reloc_howto_type howto_optcall =
116   HOWTO (R_OPTCALL, 0,2,24,true,0, complain_overflow_signed,
117          optcall_callback, "optcall", true, 0x00ffffff, 0x00ffffff, 0);
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     case BFD_RELOC_CTOR:
132       return &howto_rellong;
133     case BFD_RELOC_24_PCREL:
134       return &howto_iprmed;
135     }
136 }
137
138 /* The real code is in coffcode.h */
139
140 #define RTYPE2HOWTO(cache_ptr, dst) \
141 {                                                       \
142    reloc_howto_type *howto_ptr;                         \
143    switch ((dst)->r_type) {                             \
144      case 17: howto_ptr = &howto_rellong; break;        \
145      case 25: howto_ptr = &howto_iprmed; break;         \
146      case 27: howto_ptr = &howto_optcall; break;        \
147      default: howto_ptr = 0; break;                     \
148      }                                                  \
149    cache_ptr->howto = howto_ptr;                        \
150  }
151
152 #include "coffcode.h"
153
154 #undef coff_bfd_reloc_type_lookup
155 #define coff_bfd_reloc_type_lookup coff_i960_reloc_type_lookup
156
157 const bfd_target icoff_little_vec =
158 {
159   "coff-Intel-little",          /* name */
160   bfd_target_coff_flavour,
161   false,                        /* data byte order is little */
162   false,                        /* header byte order is little */
163
164   (HAS_RELOC | EXEC_P |         /* object flags */
165    HAS_LINENO | HAS_DEBUG |
166    HAS_SYMS | HAS_LOCALS | WP_TEXT),
167
168   (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
169   '_',                          /* leading underscore */
170   '/',                          /* ar_pad_char */
171   15,                           /* ar_max_namelen */
172
173   3,                            /* minimum alignment power */
174   bfd_getl64, bfd_getl_signed_64, bfd_putl64,
175      bfd_getl32, bfd_getl_signed_32, bfd_putl32,
176      bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* data */
177   bfd_getl64, bfd_getl_signed_64, bfd_putl64,
178      bfd_getl32, bfd_getl_signed_32, bfd_putl32,
179      bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* hdrs */
180
181  {_bfd_dummy_target, coff_object_p, /* bfd_check_format */
182    bfd_generic_archive_p, _bfd_dummy_target},
183  {bfd_false, coff_mkobject,     /* bfd_set_format */
184    _bfd_generic_mkarchive, bfd_false},
185  {bfd_false, coff_write_object_contents, /* bfd_write_contents */
186    _bfd_write_archive_contents, bfd_false},
187
188      BFD_JUMP_TABLE_GENERIC (coff),
189      BFD_JUMP_TABLE_COPY (coff),
190      BFD_JUMP_TABLE_CORE (_bfd_nocore),
191      BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff),
192      BFD_JUMP_TABLE_SYMBOLS (coff),
193      BFD_JUMP_TABLE_RELOCS (coff),
194      BFD_JUMP_TABLE_WRITE (coff),
195      BFD_JUMP_TABLE_LINK (coff),
196      BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
197
198   COFF_SWAP_TABLE,
199 };
200
201
202 const bfd_target icoff_big_vec =
203 {
204   "coff-Intel-big",             /* name */
205   bfd_target_coff_flavour,
206   false,                        /* data byte order is little */
207   true,                         /* header byte order is big */
208
209   (HAS_RELOC | EXEC_P |         /* object flags */
210    HAS_LINENO | HAS_DEBUG |
211    HAS_SYMS | HAS_LOCALS | WP_TEXT),
212
213   (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
214   '_',                          /* leading underscore */
215   '/',                          /* ar_pad_char */
216   15,                           /* ar_max_namelen */
217
218   3,                            /* minimum alignment power */
219 bfd_getl64, bfd_getl_signed_64, bfd_putl64,
220      bfd_getl32, bfd_getl_signed_32, bfd_putl32,
221      bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* data */
222 bfd_getb64, bfd_getb_signed_64, bfd_putb64,
223      bfd_getb32, bfd_getb_signed_32, bfd_putb32,
224      bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* hdrs */
225
226   {_bfd_dummy_target, coff_object_p, /* bfd_check_format */
227      bfd_generic_archive_p, _bfd_dummy_target},
228   {bfd_false, coff_mkobject,    /* bfd_set_format */
229      _bfd_generic_mkarchive, bfd_false},
230   {bfd_false, coff_write_object_contents,       /* bfd_write_contents */
231      _bfd_write_archive_contents, bfd_false},
232
233      BFD_JUMP_TABLE_GENERIC (coff),
234      BFD_JUMP_TABLE_COPY (coff),
235      BFD_JUMP_TABLE_CORE (_bfd_nocore),
236      BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff),
237      BFD_JUMP_TABLE_SYMBOLS (coff),
238      BFD_JUMP_TABLE_RELOCS (coff),
239      BFD_JUMP_TABLE_WRITE (coff),
240      BFD_JUMP_TABLE_LINK (coff),
241      BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
242
243   COFF_SWAP_TABLE,
244 };