OpenCores
URL https://opencores.org/ocsvn/open8_urisc/open8_urisc/trunk

Subversion Repositories open8_urisc

[/] [open8_urisc/] [trunk/] [gnu/] [binutils/] [bfd/] [elfxx-ia64.c] - Blame information for rev 14

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 14 khays
/* IA-64 support for 64-bit ELF
2
   Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
3
   2008, 2009, 2010, 2011  Free Software Foundation, Inc.
4
   Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
5
 
6
   This file is part of BFD, the Binary File Descriptor library.
7
 
8
   This program is free software; you can redistribute it and/or modify
9
   it under the terms of the GNU General Public License as published by
10
   the Free Software Foundation; either version 3 of the License, or
11
   (at your option) any later version.
12
 
13
   This program is distributed in the hope that it will be useful,
14
   but WITHOUT ANY WARRANTY; without even the implied warranty of
15
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
   GNU General Public License for more details.
17
 
18
   You should have received a copy of the GNU General Public License
19
   along with this program; if not, write to the Free Software
20
   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
21
   MA 02110-1301, USA.  */
22
 
23
#include "sysdep.h"
24
#include "bfd.h"
25
#include "libbfd.h"
26
#include "elf-bfd.h"
27
#include "opcode/ia64.h"
28
#include "elf/ia64.h"
29
#include "objalloc.h"
30
#include "hashtab.h"
31
#include "bfd_stdint.h"
32
#include "elfxx-ia64.h"
33
 
34
/* THE RULES for all the stuff the linker creates --
35
 
36
  GOT           Entries created in response to LTOFF or LTOFF_FPTR
37
                relocations.  Dynamic relocs created for dynamic
38
                symbols in an application; REL relocs for locals
39
                in a shared library.
40
 
41
  FPTR          The canonical function descriptor.  Created for local
42
                symbols in applications.  Descriptors for dynamic symbols
43
                and local symbols in shared libraries are created by
44
                ld.so.  Thus there are no dynamic relocs against these
45
                objects.  The FPTR relocs for such _are_ passed through
46
                to the dynamic relocation tables.
47
 
48
  FULL_PLT      Created for a PCREL21B relocation against a dynamic symbol.
49
                Requires the creation of a PLTOFF entry.  This does not
50
                require any dynamic relocations.
51
 
52
  PLTOFF        Created by PLTOFF relocations.  For local symbols, this
53
                is an alternate function descriptor, and in shared libraries
54
                requires two REL relocations.  Note that this cannot be
55
                transformed into an FPTR relocation, since it must be in
56
                range of the GP.  For dynamic symbols, this is a function
57
                descriptor for a MIN_PLT entry, and requires one IPLT reloc.
58
 
59
  MIN_PLT       Created by PLTOFF entries against dynamic symbols.  This
60
                does not require dynamic relocations.  */
61
 
62
/* ia64-specific relocation.  */
63
 
64
#define NELEMS(a)       ((int) (sizeof (a) / sizeof ((a)[0])))
65
 
66
/* Perform a relocation.  Not much to do here as all the hard work is
67
   done in elfNN_ia64_final_link_relocate.  */
68
static bfd_reloc_status_type
69
ia64_elf_reloc (bfd *abfd ATTRIBUTE_UNUSED, arelent *reloc,
70
                asymbol *sym ATTRIBUTE_UNUSED,
71
                PTR data ATTRIBUTE_UNUSED, asection *input_section,
72
                bfd *output_bfd, char **error_message)
73
{
74
  if (output_bfd)
75
    {
76
      reloc->address += input_section->output_offset;
77
      return bfd_reloc_ok;
78
    }
79
 
80
  if (input_section->flags & SEC_DEBUGGING)
81
    return bfd_reloc_continue;
82
 
83
  *error_message = "Unsupported call to ia64_elf_reloc";
84
  return bfd_reloc_notsupported;
85
}
86
 
87
#define IA64_HOWTO(TYPE, NAME, SIZE, PCREL, IN)                 \
88
  HOWTO (TYPE, 0, SIZE, 0, PCREL, 0, complain_overflow_signed,     \
89
         ia64_elf_reloc, NAME, FALSE, 0, -1, IN)
90
 
91
/* This table has to be sorted according to increasing number of the
92
   TYPE field.  */
93
static reloc_howto_type ia64_howto_table[] =
94
  {
95
    IA64_HOWTO (R_IA64_NONE,        "NONE",        0, FALSE, TRUE),
96
 
97
    IA64_HOWTO (R_IA64_IMM14,       "IMM14",       0, FALSE, TRUE),
98
    IA64_HOWTO (R_IA64_IMM22,       "IMM22",       0, FALSE, TRUE),
99
    IA64_HOWTO (R_IA64_IMM64,       "IMM64",       0, FALSE, TRUE),
100
    IA64_HOWTO (R_IA64_DIR32MSB,    "DIR32MSB",    2, FALSE, TRUE),
101
    IA64_HOWTO (R_IA64_DIR32LSB,    "DIR32LSB",    2, FALSE, TRUE),
102
    IA64_HOWTO (R_IA64_DIR64MSB,    "DIR64MSB",    4, FALSE, TRUE),
103
    IA64_HOWTO (R_IA64_DIR64LSB,    "DIR64LSB",    4, FALSE, TRUE),
104
 
105
    IA64_HOWTO (R_IA64_GPREL22,     "GPREL22",     0, FALSE, TRUE),
106
    IA64_HOWTO (R_IA64_GPREL64I,    "GPREL64I",    0, FALSE, TRUE),
107
    IA64_HOWTO (R_IA64_GPREL32MSB,  "GPREL32MSB",  2, FALSE, TRUE),
108
    IA64_HOWTO (R_IA64_GPREL32LSB,  "GPREL32LSB",  2, FALSE, TRUE),
109
    IA64_HOWTO (R_IA64_GPREL64MSB,  "GPREL64MSB",  4, FALSE, TRUE),
110
    IA64_HOWTO (R_IA64_GPREL64LSB,  "GPREL64LSB",  4, FALSE, TRUE),
111
 
112
    IA64_HOWTO (R_IA64_LTOFF22,     "LTOFF22",     0, FALSE, TRUE),
113
    IA64_HOWTO (R_IA64_LTOFF64I,    "LTOFF64I",    0, FALSE, TRUE),
114
 
115
    IA64_HOWTO (R_IA64_PLTOFF22,    "PLTOFF22",    0, FALSE, TRUE),
116
    IA64_HOWTO (R_IA64_PLTOFF64I,   "PLTOFF64I",   0, FALSE, TRUE),
117
    IA64_HOWTO (R_IA64_PLTOFF64MSB, "PLTOFF64MSB", 4, FALSE, TRUE),
118
    IA64_HOWTO (R_IA64_PLTOFF64LSB, "PLTOFF64LSB", 4, FALSE, TRUE),
119
 
120
    IA64_HOWTO (R_IA64_FPTR64I,     "FPTR64I",     0, FALSE, TRUE),
121
    IA64_HOWTO (R_IA64_FPTR32MSB,   "FPTR32MSB",   2, FALSE, TRUE),
122
    IA64_HOWTO (R_IA64_FPTR32LSB,   "FPTR32LSB",   2, FALSE, TRUE),
123
    IA64_HOWTO (R_IA64_FPTR64MSB,   "FPTR64MSB",   4, FALSE, TRUE),
124
    IA64_HOWTO (R_IA64_FPTR64LSB,   "FPTR64LSB",   4, FALSE, TRUE),
125
 
126
    IA64_HOWTO (R_IA64_PCREL60B,    "PCREL60B",    0, TRUE, TRUE),
127
    IA64_HOWTO (R_IA64_PCREL21B,    "PCREL21B",    0, TRUE, TRUE),
128
    IA64_HOWTO (R_IA64_PCREL21M,    "PCREL21M",    0, TRUE, TRUE),
129
    IA64_HOWTO (R_IA64_PCREL21F,    "PCREL21F",    0, TRUE, TRUE),
130
    IA64_HOWTO (R_IA64_PCREL32MSB,  "PCREL32MSB",  2, TRUE, TRUE),
131
    IA64_HOWTO (R_IA64_PCREL32LSB,  "PCREL32LSB",  2, TRUE, TRUE),
132
    IA64_HOWTO (R_IA64_PCREL64MSB,  "PCREL64MSB",  4, TRUE, TRUE),
133
    IA64_HOWTO (R_IA64_PCREL64LSB,  "PCREL64LSB",  4, TRUE, TRUE),
134
 
135
    IA64_HOWTO (R_IA64_LTOFF_FPTR22, "LTOFF_FPTR22", 0, FALSE, TRUE),
136
    IA64_HOWTO (R_IA64_LTOFF_FPTR64I, "LTOFF_FPTR64I", 0, FALSE, TRUE),
137
    IA64_HOWTO (R_IA64_LTOFF_FPTR32MSB, "LTOFF_FPTR32MSB", 2, FALSE, TRUE),
138
    IA64_HOWTO (R_IA64_LTOFF_FPTR32LSB, "LTOFF_FPTR32LSB", 2, FALSE, TRUE),
139
    IA64_HOWTO (R_IA64_LTOFF_FPTR64MSB, "LTOFF_FPTR64MSB", 4, FALSE, TRUE),
140
    IA64_HOWTO (R_IA64_LTOFF_FPTR64LSB, "LTOFF_FPTR64LSB", 4, FALSE, TRUE),
141
 
142
    IA64_HOWTO (R_IA64_SEGREL32MSB, "SEGREL32MSB", 2, FALSE, TRUE),
143
    IA64_HOWTO (R_IA64_SEGREL32LSB, "SEGREL32LSB", 2, FALSE, TRUE),
144
    IA64_HOWTO (R_IA64_SEGREL64MSB, "SEGREL64MSB", 4, FALSE, TRUE),
145
    IA64_HOWTO (R_IA64_SEGREL64LSB, "SEGREL64LSB", 4, FALSE, TRUE),
146
 
147
    IA64_HOWTO (R_IA64_SECREL32MSB, "SECREL32MSB", 2, FALSE, TRUE),
148
    IA64_HOWTO (R_IA64_SECREL32LSB, "SECREL32LSB", 2, FALSE, TRUE),
149
    IA64_HOWTO (R_IA64_SECREL64MSB, "SECREL64MSB", 4, FALSE, TRUE),
150
    IA64_HOWTO (R_IA64_SECREL64LSB, "SECREL64LSB", 4, FALSE, TRUE),
151
 
152
    IA64_HOWTO (R_IA64_REL32MSB,    "REL32MSB",    2, FALSE, TRUE),
153
    IA64_HOWTO (R_IA64_REL32LSB,    "REL32LSB",    2, FALSE, TRUE),
154
    IA64_HOWTO (R_IA64_REL64MSB,    "REL64MSB",    4, FALSE, TRUE),
155
    IA64_HOWTO (R_IA64_REL64LSB,    "REL64LSB",    4, FALSE, TRUE),
156
 
157
    IA64_HOWTO (R_IA64_LTV32MSB,    "LTV32MSB",    2, FALSE, TRUE),
158
    IA64_HOWTO (R_IA64_LTV32LSB,    "LTV32LSB",    2, FALSE, TRUE),
159
    IA64_HOWTO (R_IA64_LTV64MSB,    "LTV64MSB",    4, FALSE, TRUE),
160
    IA64_HOWTO (R_IA64_LTV64LSB,    "LTV64LSB",    4, FALSE, TRUE),
161
 
162
    IA64_HOWTO (R_IA64_PCREL21BI,   "PCREL21BI",   0, TRUE, TRUE),
163
    IA64_HOWTO (R_IA64_PCREL22,     "PCREL22",     0, TRUE, TRUE),
164
    IA64_HOWTO (R_IA64_PCREL64I,    "PCREL64I",    0, TRUE, TRUE),
165
 
166
    IA64_HOWTO (R_IA64_IPLTMSB,     "IPLTMSB",     4, FALSE, TRUE),
167
    IA64_HOWTO (R_IA64_IPLTLSB,     "IPLTLSB",     4, FALSE, TRUE),
168
    IA64_HOWTO (R_IA64_COPY,        "COPY",        4, FALSE, TRUE),
169
    IA64_HOWTO (R_IA64_LTOFF22X,    "LTOFF22X",    0, FALSE, TRUE),
170
    IA64_HOWTO (R_IA64_LDXMOV,      "LDXMOV",      0, FALSE, TRUE),
171
 
172
    IA64_HOWTO (R_IA64_TPREL14,     "TPREL14",     0, FALSE, FALSE),
173
    IA64_HOWTO (R_IA64_TPREL22,     "TPREL22",     0, FALSE, FALSE),
174
    IA64_HOWTO (R_IA64_TPREL64I,    "TPREL64I",    0, FALSE, FALSE),
175
    IA64_HOWTO (R_IA64_TPREL64MSB,  "TPREL64MSB",  4, FALSE, FALSE),
176
    IA64_HOWTO (R_IA64_TPREL64LSB,  "TPREL64LSB",  4, FALSE, FALSE),
177
    IA64_HOWTO (R_IA64_LTOFF_TPREL22, "LTOFF_TPREL22",  0, FALSE, FALSE),
178
 
179
    IA64_HOWTO (R_IA64_DTPMOD64MSB, "DTPMOD64MSB",  4, FALSE, FALSE),
180
    IA64_HOWTO (R_IA64_DTPMOD64LSB, "DTPMOD64LSB",  4, FALSE, FALSE),
181
    IA64_HOWTO (R_IA64_LTOFF_DTPMOD22, "LTOFF_DTPMOD22", 0, FALSE, FALSE),
182
 
183
    IA64_HOWTO (R_IA64_DTPREL14,    "DTPREL14",    0, FALSE, FALSE),
184
    IA64_HOWTO (R_IA64_DTPREL22,    "DTPREL22",    0, FALSE, FALSE),
185
    IA64_HOWTO (R_IA64_DTPREL64I,   "DTPREL64I",   0, FALSE, FALSE),
186
    IA64_HOWTO (R_IA64_DTPREL32MSB, "DTPREL32MSB", 2, FALSE, FALSE),
187
    IA64_HOWTO (R_IA64_DTPREL32LSB, "DTPREL32LSB", 2, FALSE, FALSE),
188
    IA64_HOWTO (R_IA64_DTPREL64MSB, "DTPREL64MSB", 4, FALSE, FALSE),
189
    IA64_HOWTO (R_IA64_DTPREL64LSB, "DTPREL64LSB", 4, FALSE, FALSE),
190
    IA64_HOWTO (R_IA64_LTOFF_DTPREL22, "LTOFF_DTPREL22", 0, FALSE, FALSE),
191
  };
192
 
193
static unsigned char elf_code_to_howto_index[R_IA64_MAX_RELOC_CODE + 1];
194
 
195
/* Given a BFD reloc type, return the matching HOWTO structure.  */
196
 
197
reloc_howto_type *
198
ia64_elf_lookup_howto (unsigned int rtype)
199
{
200
  static int inited = 0;
201
  int i;
202
 
203
  if (!inited)
204
    {
205
      inited = 1;
206
 
207
      memset (elf_code_to_howto_index, 0xff, sizeof (elf_code_to_howto_index));
208
      for (i = 0; i < NELEMS (ia64_howto_table); ++i)
209
        elf_code_to_howto_index[ia64_howto_table[i].type] = i;
210
    }
211
 
212
  if (rtype > R_IA64_MAX_RELOC_CODE)
213
    return 0;
214
  i = elf_code_to_howto_index[rtype];
215
  if (i >= NELEMS (ia64_howto_table))
216
    return 0;
217
  return ia64_howto_table + i;
218
}
219
 
220
reloc_howto_type*
221
ia64_elf_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
222
                            bfd_reloc_code_real_type bfd_code)
223
{
224
  unsigned int rtype;
225
 
226
  switch (bfd_code)
227
    {
228
    case BFD_RELOC_NONE:                rtype = R_IA64_NONE; break;
229
 
230
    case BFD_RELOC_IA64_IMM14:          rtype = R_IA64_IMM14; break;
231
    case BFD_RELOC_IA64_IMM22:          rtype = R_IA64_IMM22; break;
232
    case BFD_RELOC_IA64_IMM64:          rtype = R_IA64_IMM64; break;
233
 
234
    case BFD_RELOC_IA64_DIR32MSB:       rtype = R_IA64_DIR32MSB; break;
235
    case BFD_RELOC_IA64_DIR32LSB:       rtype = R_IA64_DIR32LSB; break;
236
    case BFD_RELOC_IA64_DIR64MSB:       rtype = R_IA64_DIR64MSB; break;
237
    case BFD_RELOC_IA64_DIR64LSB:       rtype = R_IA64_DIR64LSB; break;
238
 
239
    case BFD_RELOC_IA64_GPREL22:        rtype = R_IA64_GPREL22; break;
240
    case BFD_RELOC_IA64_GPREL64I:       rtype = R_IA64_GPREL64I; break;
241
    case BFD_RELOC_IA64_GPREL32MSB:     rtype = R_IA64_GPREL32MSB; break;
242
    case BFD_RELOC_IA64_GPREL32LSB:     rtype = R_IA64_GPREL32LSB; break;
243
    case BFD_RELOC_IA64_GPREL64MSB:     rtype = R_IA64_GPREL64MSB; break;
244
    case BFD_RELOC_IA64_GPREL64LSB:     rtype = R_IA64_GPREL64LSB; break;
245
 
246
    case BFD_RELOC_IA64_LTOFF22:        rtype = R_IA64_LTOFF22; break;
247
    case BFD_RELOC_IA64_LTOFF64I:       rtype = R_IA64_LTOFF64I; break;
248
 
249
    case BFD_RELOC_IA64_PLTOFF22:       rtype = R_IA64_PLTOFF22; break;
250
    case BFD_RELOC_IA64_PLTOFF64I:      rtype = R_IA64_PLTOFF64I; break;
251
    case BFD_RELOC_IA64_PLTOFF64MSB:    rtype = R_IA64_PLTOFF64MSB; break;
252
    case BFD_RELOC_IA64_PLTOFF64LSB:    rtype = R_IA64_PLTOFF64LSB; break;
253
    case BFD_RELOC_IA64_FPTR64I:        rtype = R_IA64_FPTR64I; break;
254
    case BFD_RELOC_IA64_FPTR32MSB:      rtype = R_IA64_FPTR32MSB; break;
255
    case BFD_RELOC_IA64_FPTR32LSB:      rtype = R_IA64_FPTR32LSB; break;
256
    case BFD_RELOC_IA64_FPTR64MSB:      rtype = R_IA64_FPTR64MSB; break;
257
    case BFD_RELOC_IA64_FPTR64LSB:      rtype = R_IA64_FPTR64LSB; break;
258
 
259
    case BFD_RELOC_IA64_PCREL21B:       rtype = R_IA64_PCREL21B; break;
260
    case BFD_RELOC_IA64_PCREL21BI:      rtype = R_IA64_PCREL21BI; break;
261
    case BFD_RELOC_IA64_PCREL21M:       rtype = R_IA64_PCREL21M; break;
262
    case BFD_RELOC_IA64_PCREL21F:       rtype = R_IA64_PCREL21F; break;
263
    case BFD_RELOC_IA64_PCREL22:        rtype = R_IA64_PCREL22; break;
264
    case BFD_RELOC_IA64_PCREL60B:       rtype = R_IA64_PCREL60B; break;
265
    case BFD_RELOC_IA64_PCREL64I:       rtype = R_IA64_PCREL64I; break;
266
    case BFD_RELOC_IA64_PCREL32MSB:     rtype = R_IA64_PCREL32MSB; break;
267
    case BFD_RELOC_IA64_PCREL32LSB:     rtype = R_IA64_PCREL32LSB; break;
268
    case BFD_RELOC_IA64_PCREL64MSB:     rtype = R_IA64_PCREL64MSB; break;
269
    case BFD_RELOC_IA64_PCREL64LSB:     rtype = R_IA64_PCREL64LSB; break;
270
 
271
    case BFD_RELOC_IA64_LTOFF_FPTR22:   rtype = R_IA64_LTOFF_FPTR22; break;
272
    case BFD_RELOC_IA64_LTOFF_FPTR64I:  rtype = R_IA64_LTOFF_FPTR64I; break;
273
    case BFD_RELOC_IA64_LTOFF_FPTR32MSB: rtype = R_IA64_LTOFF_FPTR32MSB; break;
274
    case BFD_RELOC_IA64_LTOFF_FPTR32LSB: rtype = R_IA64_LTOFF_FPTR32LSB; break;
275
    case BFD_RELOC_IA64_LTOFF_FPTR64MSB: rtype = R_IA64_LTOFF_FPTR64MSB; break;
276
    case BFD_RELOC_IA64_LTOFF_FPTR64LSB: rtype = R_IA64_LTOFF_FPTR64LSB; break;
277
 
278
    case BFD_RELOC_IA64_SEGREL32MSB:    rtype = R_IA64_SEGREL32MSB; break;
279
    case BFD_RELOC_IA64_SEGREL32LSB:    rtype = R_IA64_SEGREL32LSB; break;
280
    case BFD_RELOC_IA64_SEGREL64MSB:    rtype = R_IA64_SEGREL64MSB; break;
281
    case BFD_RELOC_IA64_SEGREL64LSB:    rtype = R_IA64_SEGREL64LSB; break;
282
 
283
    case BFD_RELOC_IA64_SECREL32MSB:    rtype = R_IA64_SECREL32MSB; break;
284
    case BFD_RELOC_IA64_SECREL32LSB:    rtype = R_IA64_SECREL32LSB; break;
285
    case BFD_RELOC_IA64_SECREL64MSB:    rtype = R_IA64_SECREL64MSB; break;
286
    case BFD_RELOC_IA64_SECREL64LSB:    rtype = R_IA64_SECREL64LSB; break;
287
 
288
    case BFD_RELOC_IA64_REL32MSB:       rtype = R_IA64_REL32MSB; break;
289
    case BFD_RELOC_IA64_REL32LSB:       rtype = R_IA64_REL32LSB; break;
290
    case BFD_RELOC_IA64_REL64MSB:       rtype = R_IA64_REL64MSB; break;
291
    case BFD_RELOC_IA64_REL64LSB:       rtype = R_IA64_REL64LSB; break;
292
 
293
    case BFD_RELOC_IA64_LTV32MSB:       rtype = R_IA64_LTV32MSB; break;
294
    case BFD_RELOC_IA64_LTV32LSB:       rtype = R_IA64_LTV32LSB; break;
295
    case BFD_RELOC_IA64_LTV64MSB:       rtype = R_IA64_LTV64MSB; break;
296
    case BFD_RELOC_IA64_LTV64LSB:       rtype = R_IA64_LTV64LSB; break;
297
 
298
    case BFD_RELOC_IA64_IPLTMSB:        rtype = R_IA64_IPLTMSB; break;
299
    case BFD_RELOC_IA64_IPLTLSB:        rtype = R_IA64_IPLTLSB; break;
300
    case BFD_RELOC_IA64_COPY:           rtype = R_IA64_COPY; break;
301
    case BFD_RELOC_IA64_LTOFF22X:       rtype = R_IA64_LTOFF22X; break;
302
    case BFD_RELOC_IA64_LDXMOV:         rtype = R_IA64_LDXMOV; break;
303
 
304
    case BFD_RELOC_IA64_TPREL14:        rtype = R_IA64_TPREL14; break;
305
    case BFD_RELOC_IA64_TPREL22:        rtype = R_IA64_TPREL22; break;
306
    case BFD_RELOC_IA64_TPREL64I:       rtype = R_IA64_TPREL64I; break;
307
    case BFD_RELOC_IA64_TPREL64MSB:     rtype = R_IA64_TPREL64MSB; break;
308
    case BFD_RELOC_IA64_TPREL64LSB:     rtype = R_IA64_TPREL64LSB; break;
309
    case BFD_RELOC_IA64_LTOFF_TPREL22:  rtype = R_IA64_LTOFF_TPREL22; break;
310
 
311
    case BFD_RELOC_IA64_DTPMOD64MSB:    rtype = R_IA64_DTPMOD64MSB; break;
312
    case BFD_RELOC_IA64_DTPMOD64LSB:    rtype = R_IA64_DTPMOD64LSB; break;
313
    case BFD_RELOC_IA64_LTOFF_DTPMOD22: rtype = R_IA64_LTOFF_DTPMOD22; break;
314
 
315
    case BFD_RELOC_IA64_DTPREL14:       rtype = R_IA64_DTPREL14; break;
316
    case BFD_RELOC_IA64_DTPREL22:       rtype = R_IA64_DTPREL22; break;
317
    case BFD_RELOC_IA64_DTPREL64I:      rtype = R_IA64_DTPREL64I; break;
318
    case BFD_RELOC_IA64_DTPREL32MSB:    rtype = R_IA64_DTPREL32MSB; break;
319
    case BFD_RELOC_IA64_DTPREL32LSB:    rtype = R_IA64_DTPREL32LSB; break;
320
    case BFD_RELOC_IA64_DTPREL64MSB:    rtype = R_IA64_DTPREL64MSB; break;
321
    case BFD_RELOC_IA64_DTPREL64LSB:    rtype = R_IA64_DTPREL64LSB; break;
322
    case BFD_RELOC_IA64_LTOFF_DTPREL22: rtype = R_IA64_LTOFF_DTPREL22; break;
323
 
324
    default: return 0;
325
    }
326
  return ia64_elf_lookup_howto (rtype);
327
}
328
 
329
reloc_howto_type *
330
ia64_elf_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
331
                            const char *r_name)
332
{
333
  unsigned int i;
334
 
335
  for (i = 0;
336
       i < sizeof (ia64_howto_table) / sizeof (ia64_howto_table[0]);
337
       i++)
338
    if (ia64_howto_table[i].name != NULL
339
        && strcasecmp (ia64_howto_table[i].name, r_name) == 0)
340
      return &ia64_howto_table[i];
341
 
342
  return NULL;
343
}
344
 
345
#define BTYPE_SHIFT     6
346
#define Y_SHIFT         26
347
#define X6_SHIFT        27
348
#define X4_SHIFT        27
349
#define X3_SHIFT        33
350
#define X2_SHIFT        31
351
#define X_SHIFT         33
352
#define OPCODE_SHIFT    37
353
 
354
#define OPCODE_BITS     (0xfLL << OPCODE_SHIFT)
355
#define X6_BITS         (0x3fLL << X6_SHIFT)
356
#define X4_BITS         (0xfLL << X4_SHIFT)
357
#define X3_BITS         (0x7LL << X3_SHIFT)
358
#define X2_BITS         (0x3LL << X2_SHIFT)
359
#define X_BITS          (0x1LL << X_SHIFT)
360
#define Y_BITS          (0x1LL << Y_SHIFT)
361
#define BTYPE_BITS      (0x7LL << BTYPE_SHIFT)
362
#define PREDICATE_BITS  (0x3fLL)
363
 
364
#define IS_NOP_B(i) \
365
  (((i) & (OPCODE_BITS | X6_BITS)) == (2LL << OPCODE_SHIFT))
366
#define IS_NOP_F(i) \
367
  (((i) & (OPCODE_BITS | X_BITS | X6_BITS | Y_BITS)) \
368
   == (0x1LL << X6_SHIFT))
369
#define IS_NOP_I(i) \
370
  (((i) & (OPCODE_BITS | X3_BITS | X6_BITS | Y_BITS)) \
371
   == (0x1LL << X6_SHIFT))
372
#define IS_NOP_M(i) \
373
  (((i) & (OPCODE_BITS | X3_BITS | X2_BITS | X4_BITS | Y_BITS)) \
374
   == (0x1LL << X4_SHIFT))
375
#define IS_BR_COND(i) \
376
  (((i) & (OPCODE_BITS | BTYPE_BITS)) == (0x4LL << OPCODE_SHIFT))
377
#define IS_BR_CALL(i) \
378
  (((i) & OPCODE_BITS) == (0x5LL << OPCODE_SHIFT))
379
 
380
bfd_boolean
381
ia64_elf_relax_br (bfd_byte *contents, bfd_vma off)
382
{
383
  unsigned int template_val, mlx;
384
  bfd_vma t0, t1, s0, s1, s2, br_code;
385
  long br_slot;
386
  bfd_byte *hit_addr;
387
 
388
  hit_addr = (bfd_byte *) (contents + off);
389
  br_slot = (intptr_t) hit_addr & 0x3;
390
  hit_addr -= br_slot;
391
  t0 = bfd_getl64 (hit_addr + 0);
392
  t1 = bfd_getl64 (hit_addr + 8);
393
 
394
  /* Check if we can turn br into brl.  A label is always at the start
395
     of the bundle.  Even if there are predicates on NOPs, we still
396
     perform this optimization.  */
397
  template_val = t0 & 0x1e;
398
  s0 = (t0 >> 5) & 0x1ffffffffffLL;
399
  s1 = ((t0 >> 46) | (t1 << 18)) & 0x1ffffffffffLL;
400
  s2 = (t1 >> 23) & 0x1ffffffffffLL;
401
  switch (br_slot)
402
    {
403
    case 0:
404
      /* Check if slot 1 and slot 2 are NOPs. Possible template is
405
         BBB.  We only need to check nop.b.  */
406
      if (!(IS_NOP_B (s1) && IS_NOP_B (s2)))
407
        return FALSE;
408
      br_code = s0;
409
      break;
410
    case 1:
411
      /* Check if slot 2 is NOP. Possible templates are MBB and BBB.
412
         For BBB, slot 0 also has to be nop.b.  */
413
      if (!((template_val == 0x12                               /* MBB */
414
             && IS_NOP_B (s2))
415
            || (template_val == 0x16                    /* BBB */
416
                && IS_NOP_B (s0)
417
                && IS_NOP_B (s2))))
418
        return FALSE;
419
      br_code = s1;
420
      break;
421
    case 2:
422
      /* Check if slot 1 is NOP. Possible templates are MIB, MBB, BBB,
423
         MMB and MFB. For BBB, slot 0 also has to be nop.b.  */
424
      if (!((template_val == 0x10                               /* MIB */
425
             && IS_NOP_I (s1))
426
            || (template_val == 0x12                    /* MBB */
427
                && IS_NOP_B (s1))
428
            || (template_val == 0x16                    /* BBB */
429
                && IS_NOP_B (s0)
430
                && IS_NOP_B (s1))
431
            || (template_val == 0x18                    /* MMB */
432
                && IS_NOP_M (s1))
433
            || (template_val == 0x1c                    /* MFB */
434
                && IS_NOP_F (s1))))
435
        return FALSE;
436
      br_code = s2;
437
      break;
438
    default:
439
      /* It should never happen.  */
440
      abort ();
441
    }
442
 
443
  /* We can turn br.cond/br.call into brl.cond/brl.call.  */
444
  if (!(IS_BR_COND (br_code) || IS_BR_CALL (br_code)))
445
    return FALSE;
446
 
447
  /* Turn br into brl by setting bit 40.  */
448
  br_code |= 0x1LL << 40;
449
 
450
  /* Turn the old bundle into a MLX bundle with the same stop-bit
451
     variety.  */
452
  if (t0 & 0x1)
453
    mlx = 0x5;
454
  else
455
    mlx = 0x4;
456
 
457
  if (template_val == 0x16)
458
    {
459
      /* For BBB, we need to put nop.m in slot 0.  We keep the original
460
         predicate only if slot 0 isn't br.  */
461
      if (br_slot == 0)
462
        t0 = 0LL;
463
      else
464
        t0 &= PREDICATE_BITS << 5;
465
      t0 |= 0x1LL << (X4_SHIFT + 5);
466
    }
467
  else
468
    {
469
      /* Keep the original instruction in slot 0.  */
470
      t0 &= 0x1ffffffffffLL << 5;
471
    }
472
 
473
  t0 |= mlx;
474
 
475
  /* Put brl in slot 1.  */
476
  t1 = br_code << 23;
477
 
478
  bfd_putl64 (t0, hit_addr);
479
  bfd_putl64 (t1, hit_addr + 8);
480
  return TRUE;
481
}
482
 
483
void
484
ia64_elf_relax_brl (bfd_byte *contents, bfd_vma off)
485
{
486
  int template_val;
487
  bfd_byte *hit_addr;
488
  bfd_vma t0, t1, i0, i1, i2;
489
 
490
  hit_addr = (bfd_byte *) (contents + off);
491
  hit_addr -= (intptr_t) hit_addr & 0x3;
492
  t0 = bfd_getl64 (hit_addr);
493
  t1 = bfd_getl64 (hit_addr + 8);
494
 
495
  /* Keep the instruction in slot 0. */
496
  i0 = (t0 >> 5) & 0x1ffffffffffLL;
497
  /* Use nop.b for slot 1. */
498
  i1 = 0x4000000000LL;
499
  /* For slot 2, turn brl into br by masking out bit 40.  */
500
  i2 = (t1 >> 23) & 0x0ffffffffffLL;
501
 
502
  /* Turn a MLX bundle into a MBB bundle with the same stop-bit
503
     variety.  */
504
  if (t0 & 0x1)
505
    template_val = 0x13;
506
  else
507
    template_val = 0x12;
508
  t0 = (i1 << 46) | (i0 << 5) | template_val;
509
  t1 = (i2 << 23) | (i1 >> 18);
510
 
511
  bfd_putl64 (t0, hit_addr);
512
  bfd_putl64 (t1, hit_addr + 8);
513
}
514
 
515
void
516
ia64_elf_relax_ldxmov (bfd_byte *contents, bfd_vma off)
517
{
518
  int shift, r1, r3;
519
  bfd_vma dword, insn;
520
 
521
  switch ((int)off & 0x3)
522
    {
523
    case 0: shift =  5; break;
524
    case 1: shift = 14; off += 3; break;
525
    case 2: shift = 23; off += 6; break;
526
    default:
527
      abort ();
528
    }
529
 
530
  dword = bfd_getl64 (contents + off);
531
  insn = (dword >> shift) & 0x1ffffffffffLL;
532
 
533
  r1 = (insn >> 6) & 127;
534
  r3 = (insn >> 20) & 127;
535
  if (r1 == r3)
536
    insn = 0x8000000;                              /* nop */
537
  else
538
    insn = (insn & 0x7f01fff) | 0x10800000000LL;   /* (qp) mov r1 = r3 */
539
 
540
  dword &= ~(0x1ffffffffffLL << shift);
541
  dword |= (insn << shift);
542
  bfd_putl64 (dword, contents + off);
543
}
544
 
545
bfd_reloc_status_type
546
ia64_elf_install_value (bfd_byte *hit_addr, bfd_vma v, unsigned int r_type)
547
{
548
  const struct ia64_operand *op;
549
  int bigendian = 0, shift = 0;
550
  bfd_vma t0, t1, dword;
551
  ia64_insn insn;
552
  enum ia64_opnd opnd;
553
  const char *err;
554
  size_t size = 8;
555
#ifdef BFD_HOST_U_64_BIT
556
  BFD_HOST_U_64_BIT val = (BFD_HOST_U_64_BIT) v;
557
#else
558
  bfd_vma val = v;
559
#endif
560
 
561
  opnd = IA64_OPND_NIL;
562
  switch (r_type)
563
    {
564
    case R_IA64_NONE:
565
    case R_IA64_LDXMOV:
566
      return bfd_reloc_ok;
567
 
568
      /* Instruction relocations.  */
569
 
570
    case R_IA64_IMM14:
571
    case R_IA64_TPREL14:
572
    case R_IA64_DTPREL14:
573
      opnd = IA64_OPND_IMM14;
574
      break;
575
 
576
    case R_IA64_PCREL21F:       opnd = IA64_OPND_TGT25; break;
577
    case R_IA64_PCREL21M:       opnd = IA64_OPND_TGT25b; break;
578
    case R_IA64_PCREL60B:       opnd = IA64_OPND_TGT64; break;
579
    case R_IA64_PCREL21B:
580
    case R_IA64_PCREL21BI:
581
      opnd = IA64_OPND_TGT25c;
582
      break;
583
 
584
    case R_IA64_IMM22:
585
    case R_IA64_GPREL22:
586
    case R_IA64_LTOFF22:
587
    case R_IA64_LTOFF22X:
588
    case R_IA64_PLTOFF22:
589
    case R_IA64_PCREL22:
590
    case R_IA64_LTOFF_FPTR22:
591
    case R_IA64_TPREL22:
592
    case R_IA64_DTPREL22:
593
    case R_IA64_LTOFF_TPREL22:
594
    case R_IA64_LTOFF_DTPMOD22:
595
    case R_IA64_LTOFF_DTPREL22:
596
      opnd = IA64_OPND_IMM22;
597
      break;
598
 
599
    case R_IA64_IMM64:
600
    case R_IA64_GPREL64I:
601
    case R_IA64_LTOFF64I:
602
    case R_IA64_PLTOFF64I:
603
    case R_IA64_PCREL64I:
604
    case R_IA64_FPTR64I:
605
    case R_IA64_LTOFF_FPTR64I:
606
    case R_IA64_TPREL64I:
607
    case R_IA64_DTPREL64I:
608
      opnd = IA64_OPND_IMMU64;
609
      break;
610
 
611
      /* Data relocations.  */
612
 
613
    case R_IA64_DIR32MSB:
614
    case R_IA64_GPREL32MSB:
615
    case R_IA64_FPTR32MSB:
616
    case R_IA64_PCREL32MSB:
617
    case R_IA64_LTOFF_FPTR32MSB:
618
    case R_IA64_SEGREL32MSB:
619
    case R_IA64_SECREL32MSB:
620
    case R_IA64_LTV32MSB:
621
    case R_IA64_DTPREL32MSB:
622
      size = 4; bigendian = 1;
623
      break;
624
 
625
    case R_IA64_DIR32LSB:
626
    case R_IA64_GPREL32LSB:
627
    case R_IA64_FPTR32LSB:
628
    case R_IA64_PCREL32LSB:
629
    case R_IA64_LTOFF_FPTR32LSB:
630
    case R_IA64_SEGREL32LSB:
631
    case R_IA64_SECREL32LSB:
632
    case R_IA64_LTV32LSB:
633
    case R_IA64_DTPREL32LSB:
634
      size = 4; bigendian = 0;
635
      break;
636
 
637
    case R_IA64_DIR64MSB:
638
    case R_IA64_GPREL64MSB:
639
    case R_IA64_PLTOFF64MSB:
640
    case R_IA64_FPTR64MSB:
641
    case R_IA64_PCREL64MSB:
642
    case R_IA64_LTOFF_FPTR64MSB:
643
    case R_IA64_SEGREL64MSB:
644
    case R_IA64_SECREL64MSB:
645
    case R_IA64_LTV64MSB:
646
    case R_IA64_TPREL64MSB:
647
    case R_IA64_DTPMOD64MSB:
648
    case R_IA64_DTPREL64MSB:
649
      size = 8; bigendian = 1;
650
      break;
651
 
652
    case R_IA64_DIR64LSB:
653
    case R_IA64_GPREL64LSB:
654
    case R_IA64_PLTOFF64LSB:
655
    case R_IA64_FPTR64LSB:
656
    case R_IA64_PCREL64LSB:
657
    case R_IA64_LTOFF_FPTR64LSB:
658
    case R_IA64_SEGREL64LSB:
659
    case R_IA64_SECREL64LSB:
660
    case R_IA64_LTV64LSB:
661
    case R_IA64_TPREL64LSB:
662
    case R_IA64_DTPMOD64LSB:
663
    case R_IA64_DTPREL64LSB:
664
      size = 8; bigendian = 0;
665
      break;
666
 
667
      /* Unsupported / Dynamic relocations.  */
668
    default:
669
      return bfd_reloc_notsupported;
670
    }
671
 
672
  switch (opnd)
673
    {
674
    case IA64_OPND_IMMU64:
675
      hit_addr -= (intptr_t) hit_addr & 0x3;
676
      t0 = bfd_getl64 (hit_addr);
677
      t1 = bfd_getl64 (hit_addr + 8);
678
 
679
      /* tmpl/s: bits  0.. 5 in t0
680
         slot 0: bits  5..45 in t0
681
         slot 1: bits 46..63 in t0, bits 0..22 in t1
682
         slot 2: bits 23..63 in t1 */
683
 
684
      /* First, clear the bits that form the 64 bit constant.  */
685
      t0 &= ~(0x3ffffLL << 46);
686
      t1 &= ~(0x7fffffLL
687
              | ((  (0x07fLL << 13) | (0x1ffLL << 27)
688
                    | (0x01fLL << 22) | (0x001LL << 21)
689
                    | (0x001LL << 36)) << 23));
690
 
691
      t0 |= ((val >> 22) & 0x03ffffLL) << 46;           /* 18 lsbs of imm41 */
692
      t1 |= ((val >> 40) & 0x7fffffLL) <<  0;            /* 23 msbs of imm41 */
693
      t1 |= (  (((val >>  0) & 0x07f) << 13)             /* imm7b */
694
               | (((val >>  7) & 0x1ff) << 27)          /* imm9d */
695
               | (((val >> 16) & 0x01f) << 22)          /* imm5c */
696
               | (((val >> 21) & 0x001) << 21)          /* ic */
697
               | (((val >> 63) & 0x001) << 36)) << 23;  /* i */
698
 
699
      bfd_putl64 (t0, hit_addr);
700
      bfd_putl64 (t1, hit_addr + 8);
701
      break;
702
 
703
    case IA64_OPND_TGT64:
704
      hit_addr -= (intptr_t) hit_addr & 0x3;
705
      t0 = bfd_getl64 (hit_addr);
706
      t1 = bfd_getl64 (hit_addr + 8);
707
 
708
      /* tmpl/s: bits  0.. 5 in t0
709
         slot 0: bits  5..45 in t0
710
         slot 1: bits 46..63 in t0, bits 0..22 in t1
711
         slot 2: bits 23..63 in t1 */
712
 
713
      /* First, clear the bits that form the 64 bit constant.  */
714
      t0 &= ~(0x3ffffLL << 46);
715
      t1 &= ~(0x7fffffLL
716
              | ((1LL << 36 | 0xfffffLL << 13) << 23));
717
 
718
      val >>= 4;
719
      t0 |= ((val >> 20) & 0xffffLL) << 2 << 46;        /* 16 lsbs of imm39 */
720
      t1 |= ((val >> 36) & 0x7fffffLL) << 0;             /* 23 msbs of imm39 */
721
      t1 |= ((((val >> 0) & 0xfffffLL) << 13)            /* imm20b */
722
              | (((val >> 59) & 0x1LL) << 36)) << 23;   /* i */
723
 
724
      bfd_putl64 (t0, hit_addr);
725
      bfd_putl64 (t1, hit_addr + 8);
726
      break;
727
 
728
    default:
729
      switch ((intptr_t) hit_addr & 0x3)
730
        {
731
        case 0: shift =  5; break;
732
        case 1: shift = 14; hit_addr += 3; break;
733
        case 2: shift = 23; hit_addr += 6; break;
734
        case 3: return bfd_reloc_notsupported; /* shouldn't happen...  */
735
        }
736
      dword = bfd_getl64 (hit_addr);
737
      insn = (dword >> shift) & 0x1ffffffffffLL;
738
 
739
      op = elf64_ia64_operands + opnd;
740
      err = (*op->insert) (op, val, &insn);
741
      if (err)
742
        return bfd_reloc_overflow;
743
 
744
      dword &= ~(0x1ffffffffffLL << shift);
745
      dword |= (insn << shift);
746
      bfd_putl64 (dword, hit_addr);
747
      break;
748
 
749
    case IA64_OPND_NIL:
750
      /* A data relocation.  */
751
      if (bigendian)
752
        if (size == 4)
753
          bfd_putb32 (val, hit_addr);
754
        else
755
          bfd_putb64 (val, hit_addr);
756
      else
757
        if (size == 4)
758
          bfd_putl32 (val, hit_addr);
759
        else
760
          bfd_putl64 (val, hit_addr);
761
      break;
762
    }
763
 
764
  return bfd_reloc_ok;
765
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.