* v850-tdep.c (scan_prologue): Changes to deal with scheduled
[deliverable/binutils-gdb.git] / bfd / elf32-v850.c
CommitLineData
01b49cb3
C
1/* V850-specific support for 32-bit ELF
2 Copyright (C) 1994, 1995 Free Software Foundation, Inc.
3
4This file is part of BFD, the Binary File Descriptor library.
5
6This program is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 2 of the License, or
9(at your option) any later version.
10
11This program is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with this program; if not, write to the Free Software
18Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
19
20#include "bfd.h"
21#include "sysdep.h"
22#include "libbfd.h"
23#include "elf-bfd.h"
24
25static reloc_howto_type *bfd_elf32_bfd_reloc_type_lookup
26 PARAMS ((bfd *abfd, bfd_reloc_code_real_type code));
27static void v850_info_to_howto_rel
28 PARAMS ((bfd *, arelent *, Elf32_Internal_Rel *));
e73b6ae6
JL
29static bfd_reloc_status_type bfd_elf32_v850_reloc
30 PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
31
01b49cb3
C
32
33
34/* Try to minimize the amount of space occupied by relocation tables
35 on the ROM (not that the ROM won't be swamped by other ELF overhead). */
36#define USE_REL
37
38enum reloc_type
39{
40 R_V850_NONE = 0,
41 R_V850_9_PCREL,
42 R_V850_22_PCREL,
43 R_V850_HI16_S,
44 R_V850_HI16,
45 R_V850_LO16,
237b5c4c
JL
46 R_V850_32,
47 R_V850_16,
48 R_V850_8,
b6d08fce
JL
49 R_V850_SDA_OFFSET,
50 R_V850_ZDA_OFFSET,
51 R_V850_TDA_OFFSET,
01b49cb3
C
52 R_V850_max
53};
54
55static reloc_howto_type elf_v850_howto_table[] =
56{
57 /* This reloc does nothing. */
58 HOWTO (R_V850_NONE, /* type */
59 0, /* rightshift */
60 2, /* size (0 = byte, 1 = short, 2 = long) */
61 32, /* bitsize */
62 false, /* pc_relative */
63 0, /* bitpos */
64 complain_overflow_bitfield, /* complain_on_overflow */
65 bfd_elf_generic_reloc, /* special_function */
66 "R_V850_NONE", /* name */
67 false, /* partial_inplace */
68 0, /* src_mask */
69 0, /* dst_mask */
70 false), /* pcrel_offset */
71
72 /* A PC relative 9 bit branch. */
73 HOWTO (R_V850_9_PCREL, /* type */
74 2, /* rightshift */
75 2, /* size (0 = byte, 1 = short, 2 = long) */
76 26, /* bitsize */
77 true, /* pc_relative */
78 0, /* bitpos */
79 complain_overflow_bitfield, /* complain_on_overflow */
e73b6ae6 80 bfd_elf32_v850_reloc, /* special_function */
01b49cb3
C
81 "R_V850_9_PCREL", /* name */
82 false, /* partial_inplace */
83 0x00ffffff, /* src_mask */
84 0x00ffffff, /* dst_mask */
85 true), /* pcrel_offset */
86
87 /* A PC relative 22 bit branch. */
88 HOWTO (R_V850_22_PCREL, /* type */
89 2, /* rightshift */
90 2, /* size (0 = byte, 1 = short, 2 = long) */
91 22, /* bitsize */
92 true, /* pc_relative */
93 7, /* bitpos */
94 complain_overflow_signed, /* complain_on_overflow */
e73b6ae6 95 bfd_elf32_v850_reloc, /* special_function */
01b49cb3
C
96 "R_V850_22_PCREL", /* name */
97 false, /* partial_inplace */
98 0x07ffff80, /* src_mask */
99 0x07ffff80, /* dst_mask */
100 true), /* pcrel_offset */
101
102 /* High 16 bits of symbol value. */
103 HOWTO (R_V850_HI16_S, /* type */
104 0, /* rightshift */
105 1, /* size (0 = byte, 1 = short, 2 = long) */
106 16, /* bitsize */
107 false, /* pc_relative */
e73b6ae6 108 0, /* bitpos */
01b49cb3 109 complain_overflow_dont,/* complain_on_overflow */
e73b6ae6 110 bfd_elf32_v850_reloc, /* special_function */
01b49cb3
C
111 "R_V850_HI16_S", /* name */
112 true, /* partial_inplace */
113 0xffff, /* src_mask */
114 0xffff, /* dst_mask */
115 false), /* pcrel_offset */
116
117 /* High 16 bits of symbol value. */
118 HOWTO (R_V850_HI16, /* type */
119 0, /* rightshift */
120 1, /* size (0 = byte, 1 = short, 2 = long) */
121 16, /* bitsize */
122 false, /* pc_relative */
e73b6ae6 123 0, /* bitpos */
01b49cb3 124 complain_overflow_dont,/* complain_on_overflow */
e73b6ae6 125 bfd_elf32_v850_reloc, /* special_function */
01b49cb3
C
126 "R_V850_HI16", /* name */
127 true, /* partial_inplace */
128 0xffff, /* src_mask */
129 0xffff, /* dst_mask */
130 false), /* pcrel_offset */
131
132 /* Low 16 bits of symbol value. */
133 HOWTO (R_V850_LO16, /* type */
134 0, /* rightshift */
135 1, /* size (0 = byte, 1 = short, 2 = long) */
136 16, /* bitsize */
137 false, /* pc_relative */
e73b6ae6 138 0, /* bitpos */
01b49cb3
C
139 complain_overflow_dont,/* complain_on_overflow */
140 bfd_elf_generic_reloc, /* special_function */
141 "R_V850_LO16", /* name */
142 true, /* partial_inplace */
143 0xffff, /* src_mask */
144 0xffff, /* dst_mask */
145 false), /* pcrel_offset */
237b5c4c
JL
146
147 /* Simple 32bit reloc. */
148 HOWTO (R_V850_32, /* type */
149 0, /* rightshift */
150 2, /* size (0 = byte, 1 = short, 2 = long) */
151 32, /* bitsize */
152 false, /* pc_relative */
153 0, /* bitpos */
154 complain_overflow_dont,/* complain_on_overflow */
155 bfd_elf_generic_reloc, /* special_function */
156 "R_V850_32", /* name */
e73b6ae6
JL
157 true, /* partial_inplace */
158 0xffffffff, /* src_mask */
237b5c4c
JL
159 0xffffffff, /* dst_mask */
160 false), /* pcrel_offset */
161
162 /* Simple 16bit reloc. */
163 HOWTO (R_V850_16, /* type */
164 0, /* rightshift */
165 1, /* size (0 = byte, 1 = short, 2 = long) */
166 16, /* bitsize */
167 false, /* pc_relative */
168 0, /* bitpos */
169 complain_overflow_dont,/* complain_on_overflow */
170 bfd_elf_generic_reloc, /* special_function */
171 "R_V850_16", /* name */
e73b6ae6
JL
172 true, /* partial_inplace */
173 0xffff, /* src_mask */
237b5c4c
JL
174 0xffff, /* dst_mask */
175 false), /* pcrel_offset */
176
177 /* Simple 8bit reloc. */
178 HOWTO (R_V850_8, /* type */
179 0, /* rightshift */
180 0, /* size (0 = byte, 1 = short, 2 = long) */
181 8, /* bitsize */
182 false, /* pc_relative */
183 0, /* bitpos */
184 complain_overflow_dont,/* complain_on_overflow */
185 bfd_elf_generic_reloc, /* special_function */
186 "R_V850_8", /* name */
e73b6ae6
JL
187 true, /* partial_inplace */
188 0xff, /* src_mask */
237b5c4c
JL
189 0xff, /* dst_mask */
190 false), /* pcrel_offset */
b6d08fce
JL
191
192 /* Offset from the short data area pointer. */
193 HOWTO (R_V850_SDA_OFFSET, /* type */
194 0, /* rightshift */
195 1, /* size (0 = byte, 1 = short, 2 = long) */
196 16, /* bitsize */
197 false, /* pc_relative */
198 0, /* bitpos */
199 complain_overflow_dont,/* complain_on_overflow */
200 bfd_elf_generic_reloc, /* special_function */
201 "R_V850_SDA_OFFSET", /* name */
202 true, /* partial_inplace */
203 0xffff, /* src_mask */
204 0xffff, /* dst_mask */
205 false), /* pcrel_offset */
206
207 /* Offset from the tiny data area pointer. */
208 HOWTO (R_V850_TDA_OFFSET, /* type */
209 0, /* rightshift */
210 1, /* size (0 = byte, 1 = short, 2 = long) */
211 16, /* bitsize */
212 false, /* pc_relative */
213 0, /* bitpos */
214 complain_overflow_dont,/* complain_on_overflow */
215 bfd_elf_generic_reloc, /* special_function */
216 "R_V850_TDA_OFFSET", /* name */
217 true, /* partial_inplace */
218 0xffff, /* src_mask */
219 0xffff, /* dst_mask */
220 false), /* pcrel_offset */
221
222 /* Offset from the zero data area pointer. */
223 HOWTO (R_V850_ZDA_OFFSET, /* type */
224 0, /* rightshift */
225 1, /* size (0 = byte, 1 = short, 2 = long) */
226 16, /* bitsize */
227 false, /* pc_relative */
228 0, /* bitpos */
229 complain_overflow_dont,/* complain_on_overflow */
230 bfd_elf_generic_reloc, /* special_function */
231 "R_V850_ZDA_OFFSET", /* name */
232 true, /* partial_inplace */
233 0xffff, /* src_mask */
234 0xffff, /* dst_mask */
235 false), /* pcrel_offset */
236
01b49cb3
C
237};
238
239/* Map BFD reloc types to V850 ELF reloc types. */
240
241struct v850_reloc_map
242{
243 unsigned char bfd_reloc_val;
244 unsigned char elf_reloc_val;
245};
246
247static const struct v850_reloc_map v850_reloc_map[] =
248{
249 { BFD_RELOC_NONE, R_V850_NONE, },
250 { BFD_RELOC_V850_9_PCREL, R_V850_9_PCREL, },
251 { BFD_RELOC_V850_22_PCREL, R_V850_22_PCREL, },
252 { BFD_RELOC_HI16_S, R_V850_HI16_S, },
253 { BFD_RELOC_HI16, R_V850_HI16, },
254 { BFD_RELOC_LO16, R_V850_LO16, },
237b5c4c
JL
255 { BFD_RELOC_32, R_V850_32, },
256 { BFD_RELOC_16, R_V850_16, },
257 { BFD_RELOC_8, R_V850_8, },
b6d08fce
JL
258 { BFD_RELOC_V850_TDA_OFFSET, R_V850_TDA_OFFSET, },
259 { BFD_RELOC_V850_SDA_OFFSET, R_V850_SDA_OFFSET, },
260 { BFD_RELOC_V850_ZDA_OFFSET, R_V850_ZDA_OFFSET, },
01b49cb3
C
261};
262
263static reloc_howto_type *
264bfd_elf32_bfd_reloc_type_lookup (abfd, code)
265 bfd *abfd;
266 bfd_reloc_code_real_type code;
267{
268 unsigned int i;
269
270 for (i = 0;
271 i < sizeof (v850_reloc_map) / sizeof (struct v850_reloc_map);
272 i++)
273 {
274 if (v850_reloc_map[i].bfd_reloc_val == code)
275 return &elf_v850_howto_table[v850_reloc_map[i].elf_reloc_val];
276 }
277
278 return NULL;
279}
280
281/* Set the howto pointer for an V850 ELF reloc. */
282
283static void
284v850_info_to_howto_rel (abfd, cache_ptr, dst)
285 bfd *abfd;
286 arelent *cache_ptr;
287 Elf32_Internal_Rel *dst;
288{
289 unsigned int r_type;
290
291 r_type = ELF32_R_TYPE (dst->r_info);
292 BFD_ASSERT (r_type < (unsigned int) R_V850_max);
293 cache_ptr->howto = &elf_v850_howto_table[r_type];
294}
295
e73b6ae6
JL
296static bfd_reloc_status_type
297bfd_elf32_v850_reloc (abfd, reloc, symbol, data, isection, obfd, err)
298 bfd *abfd;
299 arelent *reloc;
300 asymbol *symbol;
301 PTR data;
302 asection *isection;
303 bfd *obfd;
304 char **err;
305{
306 if (obfd != (bfd *) NULL
307 && (symbol->flags & BSF_SECTION_SYM) == 0
308 && (! reloc->howto->partial_inplace
309 || reloc->addend == 0))
310 {
311 reloc->address += isection->output_offset;
312 return bfd_reloc_ok;
313 }
314 else if (obfd != NULL)
315 {
316 return bfd_reloc_continue;
317 }
318
05f1baaa
JL
319 /* Catch relocs involving undefined symbols. */
320 if (bfd_is_und_section (symbol->section)
321 && (symbol->flags & BSF_WEAK) == 0
322 && obfd == NULL)
323 return bfd_reloc_undefined;
324
e73b6ae6
JL
325 /* We handle final linking of some relocs ourselves. */
326 {
327 long relocation, insn;
328
329 /* Is the address of the relocation really within the section? */
330 if (reloc->address > isection->_cooked_size)
331 return bfd_reloc_outofrange;
332
333 /* Work out which section the relocation is targetted at and the
334 initial relocation command value. */
335
336 /* Get symbol value. (Common symbols are special.) */
337 if (bfd_is_com_section (symbol->section))
338 relocation = 0;
339 else
340 relocation = symbol->value;
341
342 /* Convert input-section-relative symbol value to absolute + addend. */
343 relocation += symbol->section->output_section->vma;
344 relocation += symbol->section->output_offset;
345 relocation += reloc->addend;
346
347 if (reloc->howto->pc_relative == true)
348 {
349 /* Here the variable relocation holds the final address of the
350 symbol we are relocating against, plus any addend. */
351 relocation -= isection->output_section->vma + isection->output_offset;
352
353 /* Deal with pcrel_offset */
354 relocation -= reloc->address;
355 }
356
357 /* I've got no clue... */
358 reloc->addend = 0;
359
360 if (reloc->howto->type == R_V850_22_PCREL)
361 {
362 if (relocation > 0x1ffff || relocation < -0x200000)
363 return bfd_reloc_overflow;
364
365 if ((relocation % 2) != 0)
366 return bfd_reloc_dangerous;
367
368 insn = bfd_get_32 (abfd, (bfd_byte *) data + reloc->address);
e1d98a0a 369 insn &= ~0xfffe003f;
e73b6ae6
JL
370 insn |= (((relocation & 0xfffe) << 16)
371 | ((relocation & 0x3f0000) >> 16));
372 bfd_put_32 (abfd, insn, (bfd_byte *)data + reloc->address);
373 return bfd_reloc_ok;
374 }
375 else if (reloc->howto->type == R_V850_9_PCREL)
376 {
377 if (relocation > 0xff || relocation < -0x100)
378 return bfd_reloc_overflow;
379
380 if ((relocation % 2) != 0)
381 return bfd_reloc_dangerous;
382
383 insn = bfd_get_16 (abfd, (bfd_byte *) data + reloc->address);
e1d98a0a 384 insn &= 0xf870;
e73b6ae6
JL
385 insn |= ((relocation & 0x1f0) << 7) | ((relocation & 0x0e) << 3);
386 bfd_put_16 (abfd, insn, (bfd_byte *)data + reloc->address);
387 return bfd_reloc_ok;
388 }
389 else if (reloc->howto->type == R_V850_HI16_S)
390 {
1336da39 391 relocation += bfd_get_16 (abfd, (bfd_byte *) data + reloc->address);
e73b6ae6
JL
392 relocation = (relocation >> 16) + ((relocation & 0x8000) != 0);
393 bfd_put_16 (abfd, relocation, (bfd_byte *)data + reloc->address);
394 return bfd_reloc_ok;
395 }
396 else if (reloc->howto->type == R_V850_HI16)
397 {
1336da39 398 relocation += bfd_get_16 (abfd, (bfd_byte *) data + reloc->address);
e73b6ae6
JL
399 relocation = (relocation >> 16);
400 bfd_put_16 (abfd, relocation, (bfd_byte *)data + reloc->address);
401 return bfd_reloc_ok;
402 }
403 }
404
405 return bfd_reloc_continue;
406}
407
1336da39
SG
408static boolean bfd_elf32_v850_is_local_label PARAMS ((bfd *, asymbol *));
409
410/*ARGSUSED*/
411static boolean
412bfd_elf32_v850_is_local_label (abfd, symbol)
413 bfd *abfd;
414 asymbol *symbol;
415{
416 return ((symbol->name[0] == '.' && (symbol->name[1] == 'L' || symbol->name[1] == '.'))
417 || (symbol->name[0] == '_' && symbol->name[1] == '.' && symbol->name[2] == 'L'
418 && symbol->name[3] == '_'));
419}
420
421#define bfd_elf32_bfd_is_local_label bfd_elf32_v850_is_local_label
422
e73b6ae6
JL
423#define TARGET_LITTLE_SYM bfd_elf32_v850_vec
424#define TARGET_LITTLE_NAME "elf32-v850"
01b49cb3
C
425#define ELF_ARCH bfd_arch_v850
426#define ELF_MACHINE_CODE EM_CYGNUS_V850
427#define ELF_MAXPAGESIZE 0x1000
428
429#define elf_info_to_howto 0
430#define elf_info_to_howto_rel v850_info_to_howto_rel
431
1336da39
SG
432#define elf_symbol_leading_char '_'
433
01b49cb3 434#include "elf32-target.h"
This page took 0.044991 seconds and 4 git commands to generate.