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