Remove U suffix from constants for K&R compilers.
[external/binutils.git] / bfd / elf32-d30v.c
1 /* D30V-specific support for 32-bit ELF
2    Copyright (C) 1997, 98, 99, 2000 Free Software Foundation, Inc.
3    Contributed by Martin Hunt (hunt@cygnus.com).
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 #include "bfd.h"
22 #include "sysdep.h"
23 #include "libbfd.h"
24 #include "elf-bfd.h"
25
26 static reloc_howto_type *bfd_elf32_bfd_reloc_type_lookup
27   PARAMS ((bfd *abfd, bfd_reloc_code_real_type code));
28 static void d30v_info_to_howto_rel
29   PARAMS ((bfd *, arelent *, Elf32_Internal_Rel *));
30 static void d30v_info_to_howto_rela
31   PARAMS ((bfd *, arelent *, Elf32_Internal_Rela *));
32 static bfd_reloc_status_type bfd_elf_d30v_reloc PARAMS ((
33      bfd *abfd,
34      arelent *reloc_entry,
35      asymbol *symbol,
36      PTR data,
37      asection *input_section,
38      bfd *output_bfd,
39      char **error_message));
40 static bfd_reloc_status_type bfd_elf_d30v_reloc_21 PARAMS ((
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 enum reloc_type
50 {
51   R_D30V_NONE = 0,
52   R_D30V_6,
53   R_D30V_9_PCREL,
54   R_D30V_9_PCREL_R,
55   R_D30V_15,
56   R_D30V_15_PCREL,
57   R_D30V_15_PCREL_R,
58   R_D30V_21,
59   R_D30V_21_PCREL,
60   R_D30V_21_PCREL_R,
61   R_D30V_32,
62   R_D30V_32_PCREL,
63   R_D30V_32_NORMAL,
64   R_D30V_max
65 };
66
67 static reloc_howto_type elf_d30v_howto_table[] =
68 {
69   /* This reloc does nothing.  */
70   HOWTO (R_D30V_NONE,           /* type */
71          0,                     /* rightshift */
72          2,                     /* size (0 = byte, 1 = short, 2 = long) */
73          32,                    /* bitsize */
74          false,                 /* pc_relative */
75          0,                     /* bitpos */
76          complain_overflow_bitfield, /* complain_on_overflow */
77          bfd_elf_generic_reloc, /* special_function */
78          "R_D30V_NONE",         /* name */
79          false,                 /* partial_inplace */
80          0,                     /* src_mask */
81          0,                     /* dst_mask */
82          false),                /* pcrel_offset */
83
84   /* A 6 bit absolute relocation */
85   HOWTO (R_D30V_6,              /* type */
86          0,                     /* rightshift */
87          2,                     /* size (0 = byte, 1 = short, 2 = long) */
88          6,                     /* bitsize */
89          false,                 /* pc_relative */
90          0,                     /* bitpos */
91          complain_overflow_bitfield, /* complain_on_overflow */
92          bfd_elf_generic_reloc, /* special_function */
93          "R_D30V_6",            /* name */
94          false,                 /* partial_inplace */
95          0x3f,                  /* src_mask */
96          0x3f,                  /* dst_mask */
97          false),                /* pcrel_offset */
98
99   /* A relative 9 bit relocation, right shifted by 3 */
100   HOWTO (R_D30V_9_PCREL,        /* type */
101          3,                     /* rightshift */
102          2,                     /* size (0 = byte, 1 = short, 2 = long) */
103          6,                     /* bitsize */
104          true,                  /* pc_relative */
105          0,                     /* bitpos */
106          complain_overflow_signed, /* complain_on_overflow */
107          bfd_elf_d30v_reloc_21, /* special_function */
108          "R_D30V_9_PCREL",      /* name */
109          false,                 /* partial_inplace */
110          0x3f,                  /* src_mask */
111          0x3f,                  /* dst_mask */
112          true),                 /* pcrel_offset */
113
114   /* A relative 9 bit relocation, right shifted by 3 */
115   HOWTO (R_D30V_9_PCREL_R,      /* type */
116          3,                     /* rightshift */
117          2,                     /* size (0 = byte, 1 = short, 2 = long) */
118          6,                     /* bitsize */
119          true,                  /* pc_relative */
120          0,                     /* bitpos */
121          complain_overflow_signed, /* complain_on_overflow */
122          bfd_elf_d30v_reloc_21, /* special_function */
123          "R_D30V_9_PCREL_R",    /* name */
124          false,                 /* partial_inplace */
125          0x3f,                  /* src_mask */
126          0x3f,                  /* dst_mask */
127          true),                 /* pcrel_offset */
128
129   /* An absolute 15 bit relocation, right shifted by 3 */
130   HOWTO (R_D30V_15,             /* type */
131          3,                     /* rightshift */
132          2,                     /* size (0 = byte, 1 = short, 2 = long) */
133          12,                    /* bitsize */
134          false,                 /* pc_relative */
135          0,                     /* bitpos */
136          complain_overflow_signed, /* complain_on_overflow */
137          bfd_elf_generic_reloc, /* special_function */
138          "R_D30V_15",           /* name */
139          false,                 /* partial_inplace */
140          0xfff,                 /* src_mask */
141          0xfff,                 /* dst_mask */
142          false),                /* pcrel_offset */
143
144   /* A relative 15 bit relocation, right shifted by 3 */
145   HOWTO (R_D30V_15_PCREL,       /* type */
146          3,                     /* rightshift */
147          2,                     /* size (0 = byte, 1 = short, 2 = long) */
148          12,                    /* bitsize */
149          true,                  /* pc_relative */
150          0,                     /* bitpos */
151          complain_overflow_signed, /* complain_on_overflow */
152          bfd_elf_d30v_reloc_21, /* special_function */
153          "R_D30V_15_PCREL",     /* name */
154          false,                 /* partial_inplace */
155          0xfff,                 /* src_mask */
156          0xfff,                 /* dst_mask */
157          true),                 /* pcrel_offset */
158
159   /* A relative 15 bit relocation, right shifted by 3 */
160   HOWTO (R_D30V_15_PCREL_R,     /* type */
161          3,                     /* rightshift */
162          2,                     /* size (0 = byte, 1 = short, 2 = long) */
163          12,                    /* bitsize */
164          true,                  /* pc_relative */
165          0,                     /* bitpos */
166          complain_overflow_signed, /* complain_on_overflow */
167          bfd_elf_d30v_reloc_21, /* special_function */
168          "R_D30V_15_PCREL_R",   /* name */
169          false,                 /* partial_inplace */
170          0xfff,                 /* src_mask */
171          0xfff,                 /* dst_mask */
172          true),                 /* pcrel_offset */
173
174   /* An absolute 21 bit relocation, right shifted by 3 */
175   HOWTO (R_D30V_21,             /* type */
176          3,                     /* rightshift */
177          2,                     /* size (0 = byte, 1 = short, 2 = long) */
178          18,                    /* bitsize */
179          false,                 /* pc_relative */
180          0,                     /* bitpos */
181          complain_overflow_signed, /* complain_on_overflow */
182          bfd_elf_generic_reloc, /* special_function */
183          "R_D30V_21",           /* name */
184          false,                 /* partial_inplace */
185          0x3ffff,               /* src_mask */
186          0x3ffff,               /* dst_mask */
187          false),                /* pcrel_offset */
188
189   /* A relative 21 bit relocation, right shifted by 3 */
190   HOWTO (R_D30V_21_PCREL,       /* type */
191          3,                     /* rightshift */
192          2,                     /* size (0 = byte, 1 = short, 2 = long) */
193          18,                    /* bitsize */
194          true,                  /* pc_relative */
195          0,                     /* bitpos */
196          complain_overflow_signed, /* complain_on_overflow */
197          bfd_elf_d30v_reloc_21, /* special_function */
198          "R_D30V_21_PCREL",     /* name */
199          false,                 /* partial_inplace */
200          0x3ffff,               /* src_mask */
201          0x3ffff,               /* dst_mask */
202          true),                 /* pcrel_offset */
203
204   /* A relative 21 bit relocation, right shifted by 3, in the Right container */
205   HOWTO (R_D30V_21_PCREL_R,     /* type */
206          3,                     /* rightshift */
207          2,                     /* size (0 = byte, 1 = short, 2 = long) */
208          18,                    /* bitsize */
209          true,                  /* pc_relative */
210          0,                     /* bitpos */
211          complain_overflow_signed, /* complain_on_overflow */
212          bfd_elf_d30v_reloc_21, /* special_function */
213          "R_D30V_21_PCREL_R",   /* name */
214          false,                 /* partial_inplace */
215          0x3ffff,               /* src_mask */
216          0x3ffff,               /* dst_mask */
217          true),                 /* pcrel_offset */
218
219   /* A D30V 32 bit absolute relocation */
220   HOWTO (R_D30V_32,             /* type */
221          0,                     /* rightshift */
222          4,                     /* size (0 = byte, 1 = short, 2 = long) */
223          32,                    /* bitsize */
224          false,                 /* pc_relative */
225          0,                     /* bitpos */
226          complain_overflow_bitfield, /* complain_on_overflow */
227          bfd_elf_d30v_reloc,    /* special_function */
228          "R_D30V_32",           /* name */
229          false,                 /* partial_inplace */
230          0xffffffff,            /* src_mask */
231          0xffffffff,            /* dst_mask */
232          false),                /* pcrel_offset */
233
234   /* A relative 32 bit relocation */
235   HOWTO (R_D30V_32_PCREL,       /* type */
236          0,                     /* rightshift */
237          4,                     /* size (0 = byte, 1 = short, 2 = long) */
238          32,                    /* bitsize */
239          true,                  /* pc_relative */
240          0,                     /* bitpos */
241          complain_overflow_signed, /* complain_on_overflow */
242          bfd_elf_d30v_reloc,    /* special_function */
243          "R_D30V_32_PCREL",     /* name */
244          false,                 /* partial_inplace */
245          0xffffffff,            /* src_mask */
246          0xffffffff,            /* dst_mask */
247          true),                 /* pcrel_offset */
248
249   /* A regular 32 bit absolute relocation */
250   HOWTO (R_D30V_32_NORMAL,              /* type */
251          0,                     /* rightshift */
252          2,                     /* size (0 = byte, 1 = short, 2 = long) */
253          32,                    /* bitsize */
254          false,                 /* pc_relative */
255          0,                     /* bitpos */
256          complain_overflow_bitfield, /* complain_on_overflow */
257          bfd_elf_generic_reloc, /* special_function */
258          "R_D30V_32_NORMAL",            /* name */
259          false,                 /* partial_inplace */
260          0xffffffff,            /* src_mask */
261          0xffffffff,            /* dst_mask */
262          false),                /* pcrel_offset */
263
264 };
265
266 #define MAX32 ((bfd_signed_vma) 0x7fffffff)
267 #define MIN32 (- MAX32 - 1)
268
269 static bfd_reloc_status_type
270 bfd_elf_d30v_reloc (abfd, reloc_entry, symbol, data, input_section, output_bfd, error_message)
271      bfd *abfd;
272      arelent *reloc_entry;
273      asymbol *symbol;
274      PTR data;
275      asection *input_section;
276      bfd *output_bfd;
277      char **error_message;
278 {
279   bfd_signed_vma relocation;
280   bfd_vma in1, in2, num;
281   bfd_vma tmp_addr = 0;
282   bfd_reloc_status_type r;
283   asection *reloc_target_output_section;
284   bfd_size_type addr = reloc_entry->address;
285   bfd_reloc_status_type flag = bfd_reloc_ok;
286   bfd_vma output_base = 0;
287   reloc_howto_type *howto = reloc_entry->howto;
288   int make_absolute = 0;
289
290   r = bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data,
291                              input_section, output_bfd, error_message);
292   if (r != bfd_reloc_continue)
293     return r; 
294
295   /* a hacked-up version of bfd_perform_reloc() follows */
296  if (bfd_is_und_section (symbol->section)
297       && (symbol->flags & BSF_WEAK) == 0
298       && output_bfd == (bfd *) NULL)
299     flag = bfd_reloc_undefined;
300
301   /* Is the address of the relocation really within the section?  */
302   if (reloc_entry->address > input_section->_cooked_size)
303     return bfd_reloc_outofrange;
304
305   /* Work out which section the relocation is targetted at and the
306      initial relocation command value.  */
307
308   /* Get symbol value.  (Common symbols are special.)  */
309   if (bfd_is_com_section (symbol->section))
310     relocation = 0;
311   else
312     relocation = symbol->value;
313
314   reloc_target_output_section = symbol->section->output_section;
315
316   /* Convert input-section-relative symbol value to absolute.  */
317   if (output_bfd)
318     output_base = 0;
319   else
320     output_base = reloc_target_output_section->vma;
321
322   relocation += output_base + symbol->section->output_offset;
323
324   /* Add in supplied addend.  */
325   relocation += reloc_entry->addend;
326
327   /* Here the variable relocation holds the final address of the
328      symbol we are relocating against, plus any addend.  */
329
330   if (howto->pc_relative == true)
331     {
332       tmp_addr = input_section->output_section->vma + input_section->output_offset 
333         + reloc_entry->address;
334       relocation -= tmp_addr;
335     }
336   
337   if (output_bfd != (bfd *) NULL)
338     {
339       /* This is a partial relocation, and we want to apply the relocation
340          to the reloc entry rather than the raw data. Modify the reloc
341          inplace to reflect what we now know.  */
342       reloc_entry->addend = relocation;
343       reloc_entry->address += input_section->output_offset;
344       return flag;
345     }
346   else
347     reloc_entry->addend = 0;
348   
349   in1 = bfd_get_32 (abfd, (bfd_byte *) data + addr);
350   in2 = bfd_get_32 (abfd, (bfd_byte *) data + addr + 4);
351
352   /* extract the addend */
353   num = ((in2 & 0x3FFFF)
354          | ((in2 & 0xFF00000) >> 2)
355          | ((in1 & 0x3F) << 26));
356   in1 &= 0xFFFFFFC0;
357   in2 = 0x80000000;
358   
359   relocation += num;
360
361   if (howto->pc_relative == true && howto->bitsize == 32)
362     {
363       /* The D30V has a PC that doesn't wrap and PC-relative jumps are
364          signed, so a PC-relative jump can't be more than +/- 2^31 bytes.
365          If one exceeds this, change it to an absolute jump.  */
366       if (relocation > MAX32 || relocation < MIN32)
367         {
368           relocation = (relocation + tmp_addr) & 0xffffffff;
369           make_absolute = 1;
370         }
371     }
372   
373   in1 |= (relocation >> 26) & 0x3F;     /* top 6 bits */
374   in2 |= ((relocation & 0x03FC0000) << 2);  /* next 8 bits */ 
375   in2 |= relocation & 0x0003FFFF;               /* bottom 18 bits */
376   
377   /* change a PC-relative instruction to its absolute equivalent */
378   /* with this simple hack */
379   if (make_absolute)
380     in1 |= 0x00100000;
381
382   bfd_put_32 (abfd, in1, (bfd_byte *) data + addr);
383   bfd_put_32 (abfd, in2, (bfd_byte *) data + addr + 4);
384   
385   return flag;
386 }   
387
388
389 static bfd_reloc_status_type
390 bfd_elf_d30v_reloc_21 (abfd, reloc_entry, symbol, data, input_section, output_bfd, error_message)
391      bfd *abfd;
392      arelent *reloc_entry;
393      asymbol *symbol;
394      PTR data;
395      asection *input_section;
396      bfd *output_bfd;
397      char **error_message;
398 {
399   bfd_vma relocation;
400   bfd_vma in1, num;
401   bfd_reloc_status_type r;
402   asection *reloc_target_output_section;
403   bfd_size_type addr = reloc_entry->address;
404   bfd_reloc_status_type flag = bfd_reloc_ok;
405   bfd_vma output_base = 0;
406   reloc_howto_type *howto = reloc_entry->howto;
407   int mask, max;
408
409   r = bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data,
410                              input_section, output_bfd, error_message);
411   if (r != bfd_reloc_continue)
412     return r; 
413
414   /* a hacked-up version of bfd_perform_reloc() follows */
415  if (bfd_is_und_section (symbol->section)
416       && (symbol->flags & BSF_WEAK) == 0
417       && output_bfd == (bfd *) NULL)
418     flag = bfd_reloc_undefined;
419
420   /* Is the address of the relocation really within the section?  */
421   if (reloc_entry->address > input_section->_cooked_size)
422     return bfd_reloc_outofrange;
423
424   /* Work out which section the relocation is targetted at and the
425      initial relocation command value.  */
426
427   /* Get symbol value.  (Common symbols are special.)  */
428   if (bfd_is_com_section (symbol->section))
429     relocation = 0;
430   else
431     relocation = symbol->value;
432
433   reloc_target_output_section = symbol->section->output_section;
434
435   /* Convert input-section-relative symbol value to absolute.  */
436   if (output_bfd)
437     output_base = 0;
438   else
439     output_base = reloc_target_output_section->vma;
440
441   relocation += output_base + symbol->section->output_offset;
442
443   /* Add in supplied addend.  */
444   relocation += reloc_entry->addend;
445
446   /* Here the variable relocation holds the final address of the
447      symbol we are relocating against, plus any addend.  */
448
449   if (howto->pc_relative == true)
450     {
451       relocation -= input_section->output_section->vma + input_section->output_offset;
452       if (howto->pcrel_offset == true)
453         relocation -= reloc_entry->address;
454     }
455
456   if (output_bfd != (bfd *) NULL)
457     {
458       /* This is a partial relocation, and we want to apply the relocation
459          to the reloc entry rather than the raw data. Modify the reloc
460          inplace to reflect what we now know.  */
461       reloc_entry->addend = relocation;
462       reloc_entry->address += input_section->output_offset;
463       return flag;
464     }
465   else
466     reloc_entry->addend = 0;
467   
468   in1 = bfd_get_32 (abfd, (bfd_byte *) data + addr);
469
470   mask =  (1 << howto->bitsize) - 1;
471   if (howto->bitsize == 6)
472     mask <<= 12;
473   max = (1 << (howto->bitsize + 2)) - 1;
474
475   /* extract the addend */
476   num = in1 & mask;  /* 18 bits */
477   if (howto->bitsize == 6)
478     num >>= 12;
479   num <<= 3; /* shift left 3 */
480   in1 &= ~mask;  /* mask out addend */
481
482   relocation += num;
483   if (howto->type == R_D30V_21_PCREL_R || howto->type == R_D30V_15_PCREL_R ||
484       howto->type == R_D30V_9_PCREL_R )
485     {
486       relocation += 4;
487     }
488
489   if ((int)relocation < 0 )
490     {
491       if (~(int)relocation > max)
492         flag = bfd_reloc_overflow;
493     }
494   else
495     {
496       if ((int)relocation > max)
497         flag = bfd_reloc_overflow;
498     }
499   relocation >>= 3; 
500   if (howto->bitsize == 6)
501     in1 |= ((relocation & (mask >> 12)) << 12);
502   else
503     in1 |= relocation & mask;
504
505   bfd_put_32 (abfd, in1, (bfd_byte *) data + addr);
506   
507   return flag;
508 }   
509
510 /* Map BFD reloc types to D30V ELF reloc types.  */
511
512 struct d30v_reloc_map
513 {
514   bfd_reloc_code_real_type bfd_reloc_val;
515   unsigned char elf_reloc_val;
516 };
517
518
519 static const struct d30v_reloc_map d30v_reloc_map[] =
520 {
521   { BFD_RELOC_NONE, R_D30V_NONE, },
522   { BFD_RELOC_D30V_6, R_D30V_6 },
523   { BFD_RELOC_D30V_9_PCREL, R_D30V_9_PCREL },
524   { BFD_RELOC_D30V_9_PCREL_R, R_D30V_9_PCREL_R },
525   { BFD_RELOC_D30V_15, R_D30V_15 },
526   { BFD_RELOC_D30V_15_PCREL, R_D30V_15_PCREL },
527   { BFD_RELOC_D30V_15_PCREL_R, R_D30V_15_PCREL_R },
528   { BFD_RELOC_D30V_21, R_D30V_21 },
529   { BFD_RELOC_D30V_21_PCREL, R_D30V_21_PCREL },
530   { BFD_RELOC_D30V_21_PCREL_R, R_D30V_21_PCREL_R },
531   { BFD_RELOC_D30V_32, R_D30V_32 },
532   { BFD_RELOC_D30V_32_PCREL, R_D30V_32_PCREL },
533   { BFD_RELOC_32, R_D30V_32_NORMAL },
534 };
535
536 static reloc_howto_type *
537 bfd_elf32_bfd_reloc_type_lookup (abfd, code)
538      bfd *abfd ATTRIBUTE_UNUSED;
539      bfd_reloc_code_real_type code;
540 {
541   unsigned int i;
542
543   for (i = 0;
544        i < sizeof (d30v_reloc_map) / sizeof (struct d30v_reloc_map);
545        i++)
546     {
547       if (d30v_reloc_map[i].bfd_reloc_val == code)
548         return &elf_d30v_howto_table[d30v_reloc_map[i].elf_reloc_val];
549     }
550
551   return NULL;
552 }
553
554 /* Set the howto pointer for an D30V ELF reloc (type REL).  */
555
556 static void
557 d30v_info_to_howto_rel (abfd, cache_ptr, dst)
558      bfd *abfd ATTRIBUTE_UNUSED;
559      arelent *cache_ptr;
560      Elf32_Internal_Rel *dst;
561 {
562   unsigned int r_type;
563
564   r_type = ELF32_R_TYPE (dst->r_info);
565   BFD_ASSERT (r_type < (unsigned int) R_D30V_max);
566   cache_ptr->howto = &elf_d30v_howto_table[r_type];
567 }
568
569 /* Set the howto pointer for an D30V ELF reloc (type RELA).  */
570
571 static void
572 d30v_info_to_howto_rela (abfd, cache_ptr, dst)
573      bfd *abfd ATTRIBUTE_UNUSED;
574      arelent *cache_ptr;
575      Elf32_Internal_Rela *dst;
576 {
577   unsigned int r_type;
578
579   r_type = ELF32_R_TYPE (dst->r_info);
580   BFD_ASSERT (r_type < (unsigned int) R_D30V_max);
581   cache_ptr->howto = &elf_d30v_howto_table[r_type];
582 }
583
584 #define ELF_ARCH                bfd_arch_d30v
585 #define ELF_MACHINE_CODE        EM_CYGNUS_D30V
586 #define ELF_MAXPAGESIZE         0x1000
587
588 #define TARGET_BIG_SYM          bfd_elf32_d30v_vec
589 #define TARGET_BIG_NAME         "elf32-d30v"
590
591 #define elf_info_to_howto       d30v_info_to_howto_rela
592 #define elf_info_to_howto_rel   d30v_info_to_howto_rel
593 #define elf_backend_object_p    0
594 #define elf_backend_final_write_processing      0
595
596 #include "elf32-target.h"