summaryrefslogtreecommitdiffstats
path: root/meta-microblaze/recipes-devtools/binutils/binutils/0012-Patch-MicroBlaze-initial-support-for-MicroBlaze-64-b.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta-microblaze/recipes-devtools/binutils/binutils/0012-Patch-MicroBlaze-initial-support-for-MicroBlaze-64-b.patch')
-rw-r--r--meta-microblaze/recipes-devtools/binutils/binutils/0012-Patch-MicroBlaze-initial-support-for-MicroBlaze-64-b.patch5247
1 files changed, 5247 insertions, 0 deletions
diff --git a/meta-microblaze/recipes-devtools/binutils/binutils/0012-Patch-MicroBlaze-initial-support-for-MicroBlaze-64-b.patch b/meta-microblaze/recipes-devtools/binutils/binutils/0012-Patch-MicroBlaze-initial-support-for-MicroBlaze-64-b.patch
new file mode 100644
index 00000000..e0166274
--- /dev/null
+++ b/meta-microblaze/recipes-devtools/binutils/binutils/0012-Patch-MicroBlaze-initial-support-for-MicroBlaze-64-b.patch
@@ -0,0 +1,5247 @@
1From 6d3b976c0f75225614d299faca766f9043bbd2d0 Mon Sep 17 00:00:00 2001
2From: Mahesh Bodapati <mbodapat@xilinx.com>
3Date: Mon, 1 Nov 2021 19:06:53 +0530
4Subject: [PATCH 12/34] [Patch,MicroBlaze] : initial support for MicroBlaze 64
5 bit [-m64]
6
7Conflicts:
8 bfd/elf32-microblaze.c
9 include/elf/common.h
10 ld/Makefile.am
11 ld/Makefile.in
12signed-off-by:Nagaraju Mekala<nmekala@xilinx.com>
13 Mahesh Bodapati<mbodapat@xilinx.com>
14---
15 bfd/Makefile.am | 2 +
16 bfd/Makefile.in | 3 +
17 bfd/bfd-in2.h | 10 +
18 bfd/config.bfd | 4 +
19 bfd/configure | 2 +
20 bfd/configure.ac | 2 +
21 bfd/cpu-microblaze.c | 53 +-
22 bfd/elf32-microblaze.c | 59 +-
23 bfd/elf64-microblaze.c | 3612 ++++++++++++++++++++++++++++
24 bfd/libbfd.h | 2 +
25 bfd/reloc.c | 12 +
26 bfd/targets.c | 6 +
27 gas/config/tc-microblaze.c | 419 +++-
28 gas/config/tc-microblaze.h | 4 +-
29 include/elf/common.h | 1 +
30 include/elf/microblaze.h | 2 +
31 ld/Makefile.am | 4 +
32 ld/Makefile.in | 6 +
33 ld/configure.tgt | 3 +
34 ld/emulparams/elf64microblaze.sh | 23 +
35 ld/emulparams/elf64microblazeel.sh | 23 +
36 opcodes/microblaze-dis.c | 36 +-
37 opcodes/microblaze-opc.h | 162 +-
38 opcodes/microblaze-opcm.h | 24 +-
39 24 files changed, 4408 insertions(+), 66 deletions(-)
40 create mode 100644 bfd/elf64-microblaze.c
41 create mode 100644 ld/emulparams/elf64microblaze.sh
42 create mode 100644 ld/emulparams/elf64microblazeel.sh
43
44diff --git a/bfd/Makefile.am b/bfd/Makefile.am
45index 670e0598f55..c76adec960a 100644
46--- a/bfd/Makefile.am
47+++ b/bfd/Makefile.am
48@@ -563,6 +563,7 @@ BFD64_BACKENDS = \
49 elf64-riscv.lo \
50 elfxx-riscv.lo \
51 elf64-s390.lo \
52+ elf64-microblaze.lo \
53 elf64-sparc.lo \
54 elf64-tilegx.lo \
55 elf64-x86-64.lo \
56@@ -600,6 +601,7 @@ BFD64_BACKENDS_CFILES = \
57 elf64-nfp.c \
58 elf64-ppc.c \
59 elf64-s390.c \
60+ elf64-microblaze.c \
61 elf64-sparc.c \
62 elf64-tilegx.c \
63 elf64-x86-64.c \
64diff --git a/bfd/Makefile.in b/bfd/Makefile.in
65index a26f74d7199..b0420bd440f 100644
66--- a/bfd/Makefile.in
67+++ b/bfd/Makefile.in
68@@ -1027,6 +1027,7 @@ BFD64_BACKENDS = \
69 elf64-riscv.lo \
70 elfxx-riscv.lo \
71 elf64-s390.lo \
72+ elf64-microblaze.lo \
73 elf64-sparc.lo \
74 elf64-tilegx.lo \
75 elf64-x86-64.lo \
76@@ -1064,6 +1065,7 @@ BFD64_BACKENDS_CFILES = \
77 elf64-nfp.c \
78 elf64-ppc.c \
79 elf64-s390.c \
80+ elf64-microblaze.c \
81 elf64-sparc.c \
82 elf64-tilegx.c \
83 elf64-x86-64.c \
84@@ -1647,6 +1649,7 @@ distclean-compile:
85 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf64-ppc.Plo@am__quote@
86 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf64-riscv.Plo@am__quote@
87 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf64-s390.Plo@am__quote@
88+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf64-microblaze.Plo@am__quote@
89 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf64-sparc.Plo@am__quote@
90 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf64-tilegx.Plo@am__quote@
91 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf64-x86-64.Plo@am__quote@
92diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
93index 26e3bb2b34b..6cf701abf10 100644
94--- a/bfd/bfd-in2.h
95+++ b/bfd/bfd-in2.h
96@@ -5389,11 +5389,21 @@ value in two words (with an imm instruction). No relocation is
97 done here - only used for relaxing */
98 BFD_RELOC_MICROBLAZE_64_NONE,
99
100+/* This is a 64 bit reloc that stores the 32 bit pc relative
101+ * +value in two words (with an imml instruction). No relocation is
102+ * +done here - only used for relaxing */
103+ BFD_RELOC_MICROBLAZE_64,
104+
105 /* This is a 64 bit reloc that stores the 32 bit pc relative
106 value in two words (with an imm instruction). The relocation is
107 PC-relative GOT offset */
108 BFD_RELOC_MICROBLAZE_64_GOTPC,
109
110+/* This is a 64 bit reloc that stores the 32 bit pc relative
111+value in two words (with an imml instruction). The relocation is
112+PC-relative GOT offset */
113+ BFD_RELOC_MICROBLAZE_64_GPC,
114+
115 /* This is a 64 bit reloc that stores the 32 bit pc relative
116 value in two words (with an imm instruction). The relocation is
117 GOT offset */
118diff --git a/bfd/config.bfd b/bfd/config.bfd
119index a4c6c8e8854..49208534de3 100644
120--- a/bfd/config.bfd
121+++ b/bfd/config.bfd
122@@ -855,11 +855,15 @@ case "${targ}" in
123 microblazeel*-*)
124 targ_defvec=microblaze_elf32_le_vec
125 targ_selvecs=microblaze_elf32_vec
126+ targ64_selvecs=microblaze_elf64_vec
127+ targ64_selvecs=microblaze_elf64_le_vec
128 ;;
129
130 microblaze*-*)
131 targ_defvec=microblaze_elf32_vec
132 targ_selvecs=microblaze_elf32_le_vec
133+ targ64_selvecs=microblaze_elf64_vec
134+ targ64_selvecs=microblaze_elf64_le_vec
135 ;;
136
137 #ifdef BFD64
138diff --git a/bfd/configure b/bfd/configure
139index 4f591b750d8..efeb1c2d717 100755
140--- a/bfd/configure
141+++ b/bfd/configure
142@@ -13546,6 +13546,8 @@ do
143 s390_elf64_vec) tb="$tb elf64-s390.lo elf64.lo $elf"; target_size=64 ;;
144 score_elf32_be_vec) tb="$tb elf32-score.lo elf32-score7.lo elf32.lo elf64.lo $elf"; want64=true; target_size=64 ;;
145 score_elf32_le_vec) tb="$tb elf32-score.lo elf32-score7.lo elf32.lo elf64.lo $elf"; want64=true; target_size=64 ;;
146+ microblaze_elf64_vec) tb="$tb elf64-microblaze.lo elf64.lo $elf"; target_size=64 ;;
147+ microblaze_elf64_le_vec) tb="$tb elf64-microblaze.lo elf64.lo $elf"; target_size=64 ;;
148 sh_coff_vec) tb="$tb coff-sh.lo $coff" ;;
149 sh_coff_le_vec) tb="$tb coff-sh.lo $coff" ;;
150 sh_coff_small_vec) tb="$tb coff-sh.lo $coff" ;;
151diff --git a/bfd/configure.ac b/bfd/configure.ac
152index 6146efb5ae3..387a0af3703 100644
153--- a/bfd/configure.ac
154+++ b/bfd/configure.ac
155@@ -603,6 +603,8 @@ do
156 s390_elf64_vec) tb="$tb elf64-s390.lo elf64.lo $elf"; target_size=64 ;;
157 score_elf32_be_vec) tb="$tb elf32-score.lo elf32-score7.lo elf32.lo elf64.lo $elf"; want64=true; target_size=64 ;;
158 score_elf32_le_vec) tb="$tb elf32-score.lo elf32-score7.lo elf32.lo elf64.lo $elf"; want64=true; target_size=64 ;;
159+ microblaze_elf64_vec) tb="$tb elf64-microblaze.lo elf64.lo $elf"; target_size=64 ;;
160+ microblaze_elf64_le_vec) tb="$tb elf64-microblaze.lo elf64.lo $elf"; target_size=64 ;;
161 sh_coff_vec) tb="$tb coff-sh.lo $coff" ;;
162 sh_coff_le_vec) tb="$tb coff-sh.lo $coff" ;;
163 sh_coff_small_vec) tb="$tb coff-sh.lo $coff" ;;
164diff --git a/bfd/cpu-microblaze.c b/bfd/cpu-microblaze.c
165index 0c1d2b1aa69..a9abb9166cc 100644
166--- a/bfd/cpu-microblaze.c
167+++ b/bfd/cpu-microblaze.c
168@@ -23,7 +23,24 @@
169 #include "bfd.h"
170 #include "libbfd.h"
171
172-const bfd_arch_info_type bfd_microblaze_arch =
173+const bfd_arch_info_type bfd_microblaze_arch[] =
174+{
175+#if BFD_DEFAULT_TARGET_SIZE == 64
176+{
177+ 64, /* 32 bits in a word. */
178+ 64, /* 32 bits in an address. */
179+ 8, /* 8 bits in a byte. */
180+ bfd_arch_microblaze, /* Architecture. */
181+ 0, /* Machine number - 0 for now. */
182+ "microblaze", /* Architecture name. */
183+ "MicroBlaze", /* Printable name. */
184+ 3, /* Section align power. */
185+ false, /* Is this the default architecture ? */
186+ bfd_default_compatible, /* Architecture comparison function. */
187+ bfd_default_scan, /* String to architecture conversion. */
188+ bfd_arch_default_fill, /* Default fill. */
189+ &bfd_microblaze_arch[1] /* Next in list. */
190+},
191 {
192 32, /* Bits in a word. */
193 32, /* Bits in an address. */
194@@ -39,4 +56,38 @@ const bfd_arch_info_type bfd_microblaze_arch =
195 bfd_arch_default_fill, /* Default fill. */
196 NULL, /* Next in list. */
197 0 /* Maximum offset of a reloc from the start of an insn. */
198+}
199+#else
200+{
201+ 32, /* 32 bits in a word. */
202+ 32, /* 32 bits in an address. */
203+ 8, /* 8 bits in a byte. */
204+ bfd_arch_microblaze, /* Architecture. */
205+ 0, /* Machine number - 0 for now. */
206+ "microblaze", /* Architecture name. */
207+ "MicroBlaze", /* Printable name. */
208+ 3, /* Section align power. */
209+ true, /* Is this the default architecture ? */
210+ bfd_default_compatible, /* Architecture comparison function. */
211+ bfd_default_scan, /* String to architecture conversion. */
212+ bfd_arch_default_fill, /* Default fill. */
213+ &bfd_microblaze_arch[1] /* Next in list. */
214+},
215+{
216+ 64, /* 32 bits in a word. */
217+ 64, /* 32 bits in an address. */
218+ 8, /* 8 bits in a byte. */
219+ bfd_arch_microblaze, /* Architecture. */
220+ 0, /* Machine number - 0 for now. */
221+ "microblaze", /* Architecture name. */
222+ "MicroBlaze", /* Printable name. */
223+ 3, /* Section align power. */
224+ false, /* Is this the default architecture ? */
225+ bfd_default_compatible, /* Architecture comparison function. */
226+ bfd_default_scan, /* String to architecture conversion. */
227+ bfd_arch_default_fill, /* Default fill. */
228+ NULL, /* Next in list. */
229+ 0 /* Maximum offset of a reloc from the start of an insn. */
230+}
231+#endif
232 };
233diff --git a/bfd/elf32-microblaze.c b/bfd/elf32-microblaze.c
234index edde04bafe4..f20adb6fd73 100644
235--- a/bfd/elf32-microblaze.c
236+++ b/bfd/elf32-microblaze.c
237@@ -114,6 +114,20 @@ static reloc_howto_type microblaze_elf_howto_raw[] =
238 0x0000ffff, /* Dest Mask. */
239 true), /* PC relative offset? */
240
241+ HOWTO (R_MICROBLAZE_IMML_64, /* Type. */
242+ 0, /* Rightshift. */
243+ 2, /* Size (0 = byte, 1 = short, 2 = long). */
244+ 16, /* Bitsize. */
245+ true, /* PC_relative. */
246+ 0, /* Bitpos. */
247+ complain_overflow_dont, /* Complain on overflow. */
248+ bfd_elf_generic_reloc,/* Special Function. */
249+ "R_MICROBLAZE_IMML_64", /* Name. */
250+ false, /* Partial Inplace. */
251+ 0, /* Source Mask. */
252+ 0x0000ffff, /* Dest Mask. */
253+ false), /* PC relative offset? */
254+
255 /* A 64 bit relocation. Table entry not really used. */
256 HOWTO (R_MICROBLAZE_64, /* Type. */
257 0, /* Rightshift. */
258@@ -278,6 +292,21 @@ static reloc_howto_type microblaze_elf_howto_raw[] =
259 0x0000ffff, /* Dest Mask. */
260 true), /* PC relative offset? */
261
262+ /* A 64 bit GOTPC relocation. Table-entry not really used. */
263+ HOWTO (R_MICROBLAZE_GPC_64, /* Type. */
264+ 0, /* Rightshift. */
265+ 2, /* Size (0 = byte, 1 = short, 2 = long). */
266+ 16, /* Bitsize. */
267+ true, /* PC_relative. */
268+ 0, /* Bitpos. */
269+ complain_overflow_dont, /* Complain on overflow. */
270+ bfd_elf_generic_reloc, /* Special Function. */
271+ "R_MICROBLAZE_GPC_64", /* Name. */
272+ false, /* Partial Inplace. */
273+ 0, /* Source Mask. */
274+ 0x0000ffff, /* Dest Mask. */
275+ true), /* PC relative offset? */
276+
277 /* A 64 bit GOT relocation. Table-entry not really used. */
278 HOWTO (R_MICROBLAZE_GOT_64, /* Type. */
279 0, /* Rightshift. */
280@@ -617,9 +646,15 @@ microblaze_elf_reloc_type_lookup (bfd * abfd ATTRIBUTE_UNUSED,
281 case BFD_RELOC_VTABLE_ENTRY:
282 microblaze_reloc = R_MICROBLAZE_GNU_VTENTRY;
283 break;
284+ case BFD_RELOC_MICROBLAZE_64:
285+ microblaze_reloc = R_MICROBLAZE_IMML_64;
286+ break;
287 case BFD_RELOC_MICROBLAZE_64_GOTPC:
288 microblaze_reloc = R_MICROBLAZE_GOTPC_64;
289 break;
290+ case BFD_RELOC_MICROBLAZE_64_GPC:
291+ microblaze_reloc = R_MICROBLAZE_GPC_64;
292+ break;
293 case BFD_RELOC_MICROBLAZE_64_GOT:
294 microblaze_reloc = R_MICROBLAZE_GOT_64;
295 break;
296@@ -1500,7 +1535,7 @@ microblaze_elf_relocate_section (bfd *output_bfd,
297 if (r_symndx == STN_UNDEF || (input_section->flags & SEC_ALLOC) == 0)
298 {
299 relocation += addend;
300- if (r_type == R_MICROBLAZE_32)
301+ if (r_type == R_MICROBLAZE_32)// || r_type == R_MICROBLAZE_IMML_64)
302 bfd_put_32 (input_bfd, relocation, contents + offset);
303 else
304 {
305@@ -1970,6 +2005,28 @@ microblaze_elf_relax_section (bfd *abfd,
306 irel->r_addend -= calc_fixup (irel->r_addend, 0, sec);
307 }
308 break;
309+ case R_MICROBLAZE_IMML_64:
310+ {
311+ /* This was a PC-relative instruction that was
312+ completely resolved. */
313+ int sfix, efix;
314+ unsigned int val;
315+ bfd_vma target_address;
316+ target_address = irel->r_addend + irel->r_offset;
317+ sfix = calc_fixup (irel->r_offset, 0, sec);
318+ efix = calc_fixup (target_address, 0, sec);
319+
320+ /* Validate the in-band val. */
321+ val = bfd_get_32 (abfd, contents + irel->r_offset);
322+ if (val != irel->r_addend && ELF64_R_TYPE (irel->r_info) == R_MICROBLAZE_32_NONE) {
323+ fprintf(stderr, "%d: CORRUPT relax reloc %x %lx\n", __LINE__, val, irel->r_addend);
324+ }
325+ irel->r_addend -= (efix - sfix);
326+ /* Should use HOWTO. */
327+ microblaze_bfd_write_imm_value_64 (abfd, contents + irel->r_offset,
328+ irel->r_addend);
329+ }
330+ break;
331 case R_MICROBLAZE_NONE:
332 case R_MICROBLAZE_32_NONE:
333 {
334diff --git a/bfd/elf64-microblaze.c b/bfd/elf64-microblaze.c
335new file mode 100644
336index 00000000000..0faa8de73c8
337--- /dev/null
338+++ b/bfd/elf64-microblaze.c
339@@ -0,0 +1,3612 @@
340+/* Xilinx MicroBlaze-specific support for 32-bit ELF
341+
342+ Copyright (C) 2009-2021 Free Software Foundation, Inc.
343+
344+ This file is part of BFD, the Binary File Descriptor library.
345+
346+ This program is free software; you can redistribute it and/or modify
347+ it under the terms of the GNU General Public License as published by
348+ the Free Software Foundation; either version 3 of the License, or
349+ (at your option) any later version.
350+
351+ This program is distributed in the hope that it will be useful,
352+ but WITHOUT ANY WARRANTY; without even the implied warranty of
353+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
354+ GNU General Public License for more details.
355+
356+ You should have received a copy of the GNU General Public License
357+ along with this program; if not, write to the
358+ Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
359+ Boston, MA 02110-1301, USA. */
360+
361+
362+#include "sysdep.h"
363+#include "bfd.h"
364+#include "bfdlink.h"
365+#include "libbfd.h"
366+#include "elf-bfd.h"
367+#include "elf/microblaze.h"
368+#include <assert.h>
369+
370+#define USE_RELA /* Only USE_REL is actually significant, but this is
371+ here are a reminder... */
372+#define INST_WORD_SIZE 4
373+
374+static int ro_small_data_pointer = 0;
375+static int rw_small_data_pointer = 0;
376+
377+static reloc_howto_type * microblaze_elf_howto_table [(int) R_MICROBLAZE_max];
378+
379+static reloc_howto_type microblaze_elf_howto_raw[] =
380+{
381+ /* This reloc does nothing. */
382+ HOWTO (R_MICROBLAZE_NONE, /* Type. */
383+ 0, /* Rightshift. */
384+ 0, /* Size. */
385+ 0, /* Bitsize. */
386+ false, /* PC_relative. */
387+ 0, /* Bitpos. */
388+ complain_overflow_dont, /* Complain on overflow. */
389+ NULL, /* Special Function. */
390+ "R_MICROBLAZE_NONE", /* Name. */
391+ false, /* Partial Inplace. */
392+ 0, /* Source Mask. */
393+ 0, /* Dest Mask. */
394+ false), /* PC relative offset? */
395+
396+ /* A standard 32 bit relocation. */
397+ HOWTO (R_MICROBLAZE_32, /* Type. */
398+ 0, /* Rightshift. */
399+ 4, /* Size. */
400+ 32, /* Bitsize. */
401+ false, /* PC_relative. */
402+ 0, /* Bitpos. */
403+ complain_overflow_bitfield, /* Complain on overflow. */
404+ bfd_elf_generic_reloc,/* Special Function. */
405+ "R_MICROBLAZE_32", /* Name. */
406+ false, /* Partial Inplace. */
407+ 0, /* Source Mask. */
408+ 0xffffffff, /* Dest Mask. */
409+ false), /* PC relative offset? */
410+
411+ /* A standard PCREL 32 bit relocation. */
412+ HOWTO (R_MICROBLAZE_32_PCREL,/* Type. */
413+ 0, /* Rightshift. */
414+ 4, /* Size. */
415+ 32, /* Bitsize. */
416+ true, /* PC_relative. */
417+ 0, /* Bitpos. */
418+ complain_overflow_bitfield, /* Complain on overflow. */
419+ bfd_elf_generic_reloc,/* Special Function. */
420+ "R_MICROBLAZE_32_PCREL", /* Name. */
421+ true, /* Partial Inplace. */
422+ 0, /* Source Mask. */
423+ 0xffffffff, /* Dest Mask. */
424+ true), /* PC relative offset? */
425+
426+ /* A 64 bit PCREL relocation. Table-entry not really used. */
427+ HOWTO (R_MICROBLAZE_64_PCREL,/* Type. */
428+ 0, /* Rightshift. */
429+ 4, /* Size. */
430+ 16, /* Bitsize. */
431+ true, /* PC_relative. */
432+ 0, /* Bitpos. */
433+ complain_overflow_dont, /* Complain on overflow. */
434+ bfd_elf_generic_reloc,/* Special Function. */
435+ "R_MICROBLAZE_64_PCREL", /* Name. */
436+ false, /* Partial Inplace. */
437+ 0, /* Source Mask. */
438+ 0x0000ffff, /* Dest Mask. */
439+ true), /* PC relative offset? */
440+
441+ /* The low half of a PCREL 32 bit relocation. */
442+ HOWTO (R_MICROBLAZE_32_PCREL_LO, /* Type. */
443+ 0, /* Rightshift. */
444+ 4, /* Size. */
445+ 16, /* Bitsize. */
446+ true, /* PC_relative. */
447+ 0, /* Bitpos. */
448+ complain_overflow_signed, /* Complain on overflow. */
449+ bfd_elf_generic_reloc, /* Special Function. */
450+ "R_MICROBLAZE_32_PCREL_LO", /* Name. */
451+ false, /* Partial Inplace. */
452+ 0, /* Source Mask. */
453+ 0x0000ffff, /* Dest Mask. */
454+ true), /* PC relative offset? */
455+
456+ HOWTO (R_MICROBLAZE_IMML_64, /* Type. */
457+ 0, /* Rightshift. */
458+ 4, /* Size (0 = byte, 1 = short, 2 = long). */
459+ 64, /* Bitsize. */
460+ true, /* PC_relative. */
461+ 0, /* Bitpos. */
462+ complain_overflow_dont, /* Complain on overflow. */
463+ bfd_elf_generic_reloc,/* Special Function. */
464+ "R_MICROBLAZE_IMML_64", /* Name. */
465+ false, /* Partial Inplace. */
466+ 0, /* Source Mask. */
467+ 0x0000ffff, /* Dest Mask. */
468+ false), /* PC relative offset? */
469+
470+ /* A 64 bit relocation. Table entry not really used. */
471+ HOWTO (R_MICROBLAZE_64, /* Type. */
472+ 0, /* Rightshift. */
473+ 2, /* Size (0 = byte, 1 = short, 2 = long). */
474+ 16, /* Bitsize. */
475+ false, /* PC_relative. */
476+ 0, /* Bitpos. */
477+ complain_overflow_dont, /* Complain on overflow. */
478+ bfd_elf_generic_reloc,/* Special Function. */
479+ "R_MICROBLAZE_64", /* Name. */
480+ false, /* Partial Inplace. */
481+ 0, /* Source Mask. */
482+ 0x0000ffff, /* Dest Mask. */
483+ false), /* PC relative offset? */
484+
485+ /* The low half of a 32 bit relocation. */
486+ HOWTO (R_MICROBLAZE_32_LO, /* Type. */
487+ 0, /* Rightshift. */
488+ 4, /* Size. */
489+ 16, /* Bitsize. */
490+ false, /* PC_relative. */
491+ 0, /* Bitpos. */
492+ complain_overflow_signed, /* Complain on overflow. */
493+ bfd_elf_generic_reloc,/* Special Function. */
494+ "R_MICROBLAZE_32_LO", /* Name. */
495+ false, /* Partial Inplace. */
496+ 0, /* Source Mask. */
497+ 0x0000ffff, /* Dest Mask. */
498+ false), /* PC relative offset? */
499+
500+ /* Read-only small data section relocation. */
501+ HOWTO (R_MICROBLAZE_SRO32, /* Type. */
502+ 0, /* Rightshift. */
503+ 4, /* Size. */
504+ 16, /* Bitsize. */
505+ false, /* PC_relative. */
506+ 0, /* Bitpos. */
507+ complain_overflow_bitfield, /* Complain on overflow. */
508+ bfd_elf_generic_reloc,/* Special Function. */
509+ "R_MICROBLAZE_SRO32", /* Name. */
510+ false, /* Partial Inplace. */
511+ 0, /* Source Mask. */
512+ 0x0000ffff, /* Dest Mask. */
513+ false), /* PC relative offset? */
514+
515+ /* Read-write small data area relocation. */
516+ HOWTO (R_MICROBLAZE_SRW32, /* Type. */
517+ 0, /* Rightshift. */
518+ 4, /* Size. */
519+ 16, /* Bitsize. */
520+ false, /* PC_relative. */
521+ 0, /* Bitpos. */
522+ complain_overflow_bitfield, /* Complain on overflow. */
523+ bfd_elf_generic_reloc,/* Special Function. */
524+ "R_MICROBLAZE_SRW32", /* Name. */
525+ false, /* Partial Inplace. */
526+ 0, /* Source Mask. */
527+ 0x0000ffff, /* Dest Mask. */
528+ false), /* PC relative offset? */
529+
530+ /* This reloc does nothing. Used for relaxation. */
531+ HOWTO (R_MICROBLAZE_32_NONE, /* Type. */
532+ 0, /* Rightshift. */
533+ 2, /* Size (0 = byte, 1 = short, 2 = long). */
534+ 32, /* Bitsize. */
535+ true, /* PC_relative. */
536+ 0, /* Bitpos. */
537+ complain_overflow_bitfield, /* Complain on overflow. */
538+ NULL, /* Special Function. */
539+ "R_MICROBLAZE_32_NONE",/* Name. */
540+ false, /* Partial Inplace. */
541+ 0, /* Source Mask. */
542+ 0, /* Dest Mask. */
543+ false), /* PC relative offset? */
544+
545+ /* This reloc does nothing. Used for relaxation. */
546+ HOWTO (R_MICROBLAZE_64_NONE, /* Type. */
547+ 0, /* Rightshift. */
548+ 0, /* Size. */
549+ 0, /* Bitsize. */
550+ true, /* PC_relative. */
551+ 0, /* Bitpos. */
552+ complain_overflow_dont, /* Complain on overflow. */
553+ NULL, /* Special Function. */
554+ "R_MICROBLAZE_64_NONE",/* Name. */
555+ false, /* Partial Inplace. */
556+ 0, /* Source Mask. */
557+ 0, /* Dest Mask. */
558+ false), /* PC relative offset? */
559+
560+ /* Symbol Op Symbol relocation. */
561+ HOWTO (R_MICROBLAZE_32_SYM_OP_SYM, /* Type. */
562+ 0, /* Rightshift. */
563+ 4, /* Size. */
564+ 32, /* Bitsize. */
565+ false, /* PC_relative. */
566+ 0, /* Bitpos. */
567+ complain_overflow_bitfield, /* Complain on overflow. */
568+ bfd_elf_generic_reloc,/* Special Function. */
569+ "R_MICROBLAZE_32_SYM_OP_SYM", /* Name. */
570+ false, /* Partial Inplace. */
571+ 0, /* Source Mask. */
572+ 0xffffffff, /* Dest Mask. */
573+ false), /* PC relative offset? */
574+
575+ /* GNU extension to record C++ vtable hierarchy. */
576+ HOWTO (R_MICROBLAZE_GNU_VTINHERIT, /* Type. */
577+ 0, /* Rightshift. */
578+ 4, /* Size. */
579+ 0, /* Bitsize. */
580+ false, /* PC_relative. */
581+ 0, /* Bitpos. */
582+ complain_overflow_dont,/* Complain on overflow. */
583+ NULL, /* Special Function. */
584+ "R_MICROBLAZE_GNU_VTINHERIT", /* Name. */
585+ false, /* Partial Inplace. */
586+ 0, /* Source Mask. */
587+ 0, /* Dest Mask. */
588+ false), /* PC relative offset? */
589+
590+ /* GNU extension to record C++ vtable member usage. */
591+ HOWTO (R_MICROBLAZE_GNU_VTENTRY, /* Type. */
592+ 0, /* Rightshift. */
593+ 4, /* Size. */
594+ 0, /* Bitsize. */
595+ false, /* PC_relative. */
596+ 0, /* Bitpos. */
597+ complain_overflow_dont,/* Complain on overflow. */
598+ _bfd_elf_rel_vtable_reloc_fn, /* Special Function. */
599+ "R_MICROBLAZE_GNU_VTENTRY", /* Name. */
600+ false, /* Partial Inplace. */
601+ 0, /* Source Mask. */
602+ 0, /* Dest Mask. */
603+ false), /* PC relative offset? */
604+
605+ /* A 64 bit GOTPC relocation. Table-entry not really used. */
606+ HOWTO (R_MICROBLAZE_GOTPC_64, /* Type. */
607+ 0, /* Rightshift. */
608+ 4, /* Size. */
609+ 16, /* Bitsize. */
610+ true, /* PC_relative. */
611+ 0, /* Bitpos. */
612+ complain_overflow_dont, /* Complain on overflow. */
613+ bfd_elf_generic_reloc, /* Special Function. */
614+ "R_MICROBLAZE_GOTPC_64", /* Name. */
615+ false, /* Partial Inplace. */
616+ 0, /* Source Mask. */
617+ 0x0000ffff, /* Dest Mask. */
618+ true), /* PC relative offset? */
619+
620+ /* A 64 bit TEXTPCREL relocation. Table-entry not really used. */
621+ HOWTO (R_MICROBLAZE_TEXTPCREL_64, /* Type. */
622+ 0, /* Rightshift. */
623+ 2, /* Size (0 = byte, 1 = short, 2 = long). */
624+ 16, /* Bitsize. */
625+ true, /* PC_relative. */
626+ 0, /* Bitpos. */
627+ complain_overflow_dont, /* Complain on overflow. */
628+ bfd_elf_generic_reloc, /* Special Function. */
629+ "R_MICROBLAZE_TEXTPCREL_64", /* Name. */
630+ false, /* Partial Inplace. */
631+ 0, /* Source Mask. */
632+ 0x0000ffff, /* Dest Mask. */
633+ true), /* PC relative offset? */
634+
635+ /* A 64 bit GOTPC relocation. Table-entry not really used. */
636+ HOWTO (R_MICROBLAZE_GPC_64, /* Type. */
637+ 0, /* Rightshift. */
638+ 2, /* Size (0 = byte, 1 = short, 2 = long). */
639+ 16, /* Bitsize. */
640+ true, /* PC_relative. */
641+ 0, /* Bitpos. */
642+ complain_overflow_dont, /* Complain on overflow. */
643+ bfd_elf_generic_reloc, /* Special Function. */
644+ "R_MICROBLAZE_GPC_64", /* Name. */
645+ false, /* Partial Inplace. */
646+ 0, /* Source Mask. */
647+ 0x0000ffff, /* Dest Mask. */
648+ true), /* PC relative offset? */
649+
650+ /* A 64 bit GOT relocation. Table-entry not really used. */
651+ HOWTO (R_MICROBLAZE_GOT_64, /* Type. */
652+ 0, /* Rightshift. */
653+ 2, /* Size (0 = byte, 1 = short, 2 = long). */
654+ 16, /* Bitsize. */
655+ false, /* PC_relative. */
656+ 0, /* Bitpos. */
657+ complain_overflow_dont, /* Complain on overflow. */
658+ bfd_elf_generic_reloc,/* Special Function. */
659+ "R_MICROBLAZE_GOT_64",/* Name. */
660+ false, /* Partial Inplace. */
661+ 0, /* Source Mask. */
662+ 0x0000ffff, /* Dest Mask. */
663+ false), /* PC relative offset? */
664+
665+ /* A 64 bit TEXTREL relocation. Table-entry not really used. */
666+ HOWTO (R_MICROBLAZE_TEXTREL_64, /* Type. */
667+ 0, /* Rightshift. */
668+ 2, /* Size (0 = byte, 1 = short, 2 = long). */
669+ 16, /* Bitsize. */
670+ false, /* PC_relative. */
671+ 0, /* Bitpos. */
672+ complain_overflow_dont, /* Complain on overflow. */
673+ bfd_elf_generic_reloc,/* Special Function. */
674+ "R_MICROBLAZE_TEXTREL_64",/* Name. */
675+ false, /* Partial Inplace. */
676+ 0, /* Source Mask. */
677+ 0x0000ffff, /* Dest Mask. */
678+ false), /* PC relative offset? */
679+
680+ /* A 64 bit PLT relocation. Table-entry not really used. */
681+ HOWTO (R_MICROBLAZE_PLT_64, /* Type. */
682+ 0, /* Rightshift. */
683+ 4, /* Size. */
684+ 16, /* Bitsize. */
685+ true, /* PC_relative. */
686+ 0, /* Bitpos. */
687+ complain_overflow_dont, /* Complain on overflow. */
688+ bfd_elf_generic_reloc,/* Special Function. */
689+ "R_MICROBLAZE_PLT_64",/* Name. */
690+ false, /* Partial Inplace. */
691+ 0, /* Source Mask. */
692+ 0x0000ffff, /* Dest Mask. */
693+ true), /* PC relative offset? */
694+
695+ /* Table-entry not really used. */
696+ HOWTO (R_MICROBLAZE_REL, /* Type. */
697+ 0, /* Rightshift. */
698+ 4, /* Size. */
699+ 16, /* Bitsize. */
700+ true, /* PC_relative. */
701+ 0, /* Bitpos. */
702+ complain_overflow_dont, /* Complain on overflow. */
703+ bfd_elf_generic_reloc,/* Special Function. */
704+ "R_MICROBLAZE_REL", /* Name. */
705+ false, /* Partial Inplace. */
706+ 0, /* Source Mask. */
707+ 0x0000ffff, /* Dest Mask. */
708+ true), /* PC relative offset? */
709+
710+ /* Table-entry not really used. */
711+ HOWTO (R_MICROBLAZE_JUMP_SLOT,/* Type. */
712+ 0, /* Rightshift. */
713+ 4, /* Size. */
714+ 16, /* Bitsize. */
715+ true, /* PC_relative. */
716+ 0, /* Bitpos. */
717+ complain_overflow_dont, /* Complain on overflow. */
718+ bfd_elf_generic_reloc,/* Special Function. */
719+ "R_MICROBLAZE_JUMP_SLOT", /* Name. */
720+ false, /* Partial Inplace. */
721+ 0, /* Source Mask. */
722+ 0x0000ffff, /* Dest Mask. */
723+ true), /* PC relative offset? */
724+
725+ /* Table-entry not really used. */
726+ HOWTO (R_MICROBLAZE_GLOB_DAT,/* Type. */
727+ 0, /* Rightshift. */
728+ 4, /* Size. */
729+ 16, /* Bitsize. */
730+ true, /* PC_relative. */
731+ 0, /* Bitpos. */
732+ complain_overflow_dont, /* Complain on overflow. */
733+ bfd_elf_generic_reloc,/* Special Function. */
734+ "R_MICROBLAZE_GLOB_DAT", /* Name. */
735+ false, /* Partial Inplace. */
736+ 0, /* Source Mask. */
737+ 0x0000ffff, /* Dest Mask. */
738+ true), /* PC relative offset? */
739+
740+ /* A 64 bit GOT relative relocation. Table-entry not really used. */
741+ HOWTO (R_MICROBLAZE_GOTOFF_64, /* Type. */
742+ 0, /* Rightshift. */
743+ 4, /* Size. */
744+ 16, /* Bitsize. */
745+ false, /* PC_relative. */
746+ 0, /* Bitpos. */
747+ complain_overflow_dont, /* Complain on overflow. */
748+ bfd_elf_generic_reloc,/* Special Function. */
749+ "R_MICROBLAZE_GOTOFF_64", /* Name. */
750+ false, /* Partial Inplace. */
751+ 0, /* Source Mask. */
752+ 0x0000ffff, /* Dest Mask. */
753+ false), /* PC relative offset? */
754+
755+ /* A 32 bit GOT relative relocation. Table-entry not really used. */
756+ HOWTO (R_MICROBLAZE_GOTOFF_32, /* Type. */
757+ 0, /* Rightshift. */
758+ 4, /* Size. */
759+ 16, /* Bitsize. */
760+ false, /* PC_relative. */
761+ 0, /* Bitpos. */
762+ complain_overflow_dont, /* Complain on overflow. */
763+ bfd_elf_generic_reloc, /* Special Function. */
764+ "R_MICROBLAZE_GOTOFF_32", /* Name. */
765+ false, /* Partial Inplace. */
766+ 0, /* Source Mask. */
767+ 0x0000ffff, /* Dest Mask. */
768+ false), /* PC relative offset? */
769+
770+ /* COPY relocation. Table-entry not really used. */
771+ HOWTO (R_MICROBLAZE_COPY, /* Type. */
772+ 0, /* Rightshift. */
773+ 4, /* Size. */
774+ 16, /* Bitsize. */
775+ false, /* PC_relative. */
776+ 0, /* Bitpos. */
777+ complain_overflow_dont, /* Complain on overflow. */
778+ bfd_elf_generic_reloc,/* Special Function. */
779+ "R_MICROBLAZE_COPY", /* Name. */
780+ false, /* Partial Inplace. */
781+ 0, /* Source Mask. */
782+ 0x0000ffff, /* Dest Mask. */
783+ false), /* PC relative offset? */
784+
785+ /* Marker relocs for TLS. */
786+ HOWTO (R_MICROBLAZE_TLS,
787+ 0, /* rightshift */
788+ 2, /* size (0 = byte, 1 = short, 2 = long) */
789+ 32, /* bitsize */
790+ false, /* pc_relative */
791+ 0, /* bitpos */
792+ complain_overflow_dont, /* complain_on_overflow */
793+ bfd_elf_generic_reloc, /* special_function */
794+ "R_MICROBLAZE_TLS", /* name */
795+ false, /* partial_inplace */
796+ 0, /* src_mask */
797+ 0x0000ffff, /* dst_mask */
798+ false), /* pcrel_offset */
799+
800+ HOWTO (R_MICROBLAZE_TLSGD,
801+ 0, /* rightshift */
802+ 4, /* size */
803+ 32, /* bitsize */
804+ false, /* pc_relative */
805+ 0, /* bitpos */
806+ complain_overflow_dont, /* complain_on_overflow */
807+ bfd_elf_generic_reloc, /* special_function */
808+ "R_MICROBLAZE_TLSGD", /* name */
809+ false, /* partial_inplace */
810+ 0, /* src_mask */
811+ 0x0000ffff, /* dst_mask */
812+ false), /* pcrel_offset */
813+
814+ HOWTO (R_MICROBLAZE_TLSLD,
815+ 0, /* rightshift */
816+ 2, /* size (0 = byte, 1 = short, 2 = long) */
817+ 32, /* bitsize */
818+ false, /* pc_relative */
819+ 0, /* bitpos */
820+ complain_overflow_dont, /* complain_on_overflow */
821+ bfd_elf_generic_reloc, /* special_function */
822+ "R_MICROBLAZE_TLSLD", /* name */
823+ false, /* partial_inplace */
824+ 0, /* src_mask */
825+ 0x0000ffff, /* dst_mask */
826+ false), /* pcrel_offset */
827+
828+ /* Computes the load module index of the load module that contains the
829+ definition of its TLS sym. */
830+ HOWTO (R_MICROBLAZE_TLSDTPMOD32,
831+ 0, /* rightshift */
832+ 2, /* size (0 = byte, 1 = short, 2 = long) */
833+ 32, /* bitsize */
834+ false, /* pc_relative */
835+ 0, /* bitpos */
836+ complain_overflow_dont, /* complain_on_overflow */
837+ bfd_elf_generic_reloc, /* special_function */
838+ "R_MICROBLAZE_TLSDTPMOD32", /* name */
839+ false, /* partial_inplace */
840+ 0, /* src_mask */
841+ 0x0000ffff, /* dst_mask */
842+ false), /* pcrel_offset */
843+
844+ /* Computes a dtv-relative displacement, the difference between the value
845+ of sym+add and the base address of the thread-local storage block that
846+ contains the definition of sym, minus 0x8000. Used for initializing GOT */
847+ HOWTO (R_MICROBLAZE_TLSDTPREL32,
848+ 0, /* rightshift */
849+ 4, /* size */
850+ 32, /* bitsize */
851+ false, /* pc_relative */
852+ 0, /* bitpos */
853+ complain_overflow_dont, /* complain_on_overflow */
854+ bfd_elf_generic_reloc, /* special_function */
855+ "R_MICROBLAZE_TLSDTPREL32", /* name */
856+ false, /* partial_inplace */
857+ 0, /* src_mask */
858+ 0x0000ffff, /* dst_mask */
859+ false), /* pcrel_offset */
860+
861+ /* Computes a dtv-relative displacement, the difference between the value
862+ of sym+add and the base address of the thread-local storage block that
863+ contains the definition of sym, minus 0x8000. */
864+ HOWTO (R_MICROBLAZE_TLSDTPREL64,
865+ 0, /* rightshift */
866+ 4, /* size */
867+ 32, /* bitsize */
868+ false, /* pc_relative */
869+ 0, /* bitpos */
870+ complain_overflow_dont, /* complain_on_overflow */
871+ bfd_elf_generic_reloc, /* special_function */
872+ "R_MICROBLAZE_TLSDTPREL64", /* name */
873+ false, /* partial_inplace */
874+ 0, /* src_mask */
875+ 0x0000ffff, /* dst_mask */
876+ false), /* pcrel_offset */
877+
878+ /* Computes a tp-relative displacement, the difference between the value of
879+ sym+add and the value of the thread pointer (r13). */
880+ HOWTO (R_MICROBLAZE_TLSGOTTPREL32,
881+ 0, /* rightshift */
882+ 4, /* size */
883+ 32, /* bitsize */
884+ false, /* pc_relative */
885+ 0, /* bitpos */
886+ complain_overflow_dont, /* complain_on_overflow */
887+ bfd_elf_generic_reloc, /* special_function */
888+ "R_MICROBLAZE_TLSGOTTPREL32", /* name */
889+ false, /* partial_inplace */
890+ 0, /* src_mask */
891+ 0x0000ffff, /* dst_mask */
892+ false), /* pcrel_offset */
893+
894+ /* Computes a tp-relative displacement, the difference between the value of
895+ sym+add and the value of the thread pointer (r13). */
896+ HOWTO (R_MICROBLAZE_TLSTPREL32,
897+ 0, /* rightshift */
898+ 4, /* size */
899+ 32, /* bitsize */
900+ false, /* pc_relative */
901+ 0, /* bitpos */
902+ complain_overflow_dont, /* complain_on_overflow */
903+ bfd_elf_generic_reloc, /* special_function */
904+ "R_MICROBLAZE_TLSTPREL32", /* name */
905+ false, /* partial_inplace */
906+ 0, /* src_mask */
907+ 0x0000ffff, /* dst_mask */
908+ false), /* pcrel_offset */
909+
910+};
911+
912+#ifndef NUM_ELEM
913+#define NUM_ELEM(a) (sizeof (a) / sizeof (a)[0])
914+#endif
915+
916+/* Initialize the microblaze_elf_howto_table, so that linear accesses can be done. */
917+
918+static void
919+microblaze_elf_howto_init (void)
920+{
921+ unsigned int i;
922+
923+ for (i = NUM_ELEM (microblaze_elf_howto_raw); i--;)
924+ {
925+ unsigned int type;
926+
927+ type = microblaze_elf_howto_raw[i].type;
928+
929+ BFD_ASSERT (type < NUM_ELEM (microblaze_elf_howto_table));
930+
931+ microblaze_elf_howto_table [type] = & microblaze_elf_howto_raw [i];
932+ }
933+}
934+
935+static reloc_howto_type *
936+microblaze_elf_reloc_type_lookup (bfd * abfd ATTRIBUTE_UNUSED,
937+ bfd_reloc_code_real_type code)
938+{
939+ enum elf_microblaze_reloc_type microblaze_reloc = R_MICROBLAZE_NONE;
940+
941+ switch (code)
942+ {
943+ case BFD_RELOC_NONE:
944+ microblaze_reloc = R_MICROBLAZE_NONE;
945+ break;
946+ case BFD_RELOC_MICROBLAZE_32_NONE:
947+ microblaze_reloc = R_MICROBLAZE_32_NONE;
948+ break;
949+ case BFD_RELOC_MICROBLAZE_64_NONE:
950+ microblaze_reloc = R_MICROBLAZE_64_NONE;
951+ break;
952+ case BFD_RELOC_32:
953+ microblaze_reloc = R_MICROBLAZE_32;
954+ break;
955+ /* RVA is treated the same as 32 */
956+ case BFD_RELOC_RVA:
957+ microblaze_reloc = R_MICROBLAZE_32;
958+ break;
959+ case BFD_RELOC_32_PCREL:
960+ microblaze_reloc = R_MICROBLAZE_32_PCREL;
961+ break;
962+ case BFD_RELOC_64_PCREL:
963+ microblaze_reloc = R_MICROBLAZE_64_PCREL;
964+ break;
965+ case BFD_RELOC_MICROBLAZE_32_LO_PCREL:
966+ microblaze_reloc = R_MICROBLAZE_32_PCREL_LO;
967+ break;
968+ case BFD_RELOC_64:
969+ microblaze_reloc = R_MICROBLAZE_64;
970+ break;
971+ case BFD_RELOC_MICROBLAZE_32_LO:
972+ microblaze_reloc = R_MICROBLAZE_32_LO;
973+ break;
974+ case BFD_RELOC_MICROBLAZE_32_ROSDA:
975+ microblaze_reloc = R_MICROBLAZE_SRO32;
976+ break;
977+ case BFD_RELOC_MICROBLAZE_32_RWSDA:
978+ microblaze_reloc = R_MICROBLAZE_SRW32;
979+ break;
980+ case BFD_RELOC_MICROBLAZE_32_SYM_OP_SYM:
981+ microblaze_reloc = R_MICROBLAZE_32_SYM_OP_SYM;
982+ break;
983+ case BFD_RELOC_VTABLE_INHERIT:
984+ microblaze_reloc = R_MICROBLAZE_GNU_VTINHERIT;
985+ break;
986+ case BFD_RELOC_VTABLE_ENTRY:
987+ microblaze_reloc = R_MICROBLAZE_GNU_VTENTRY;
988+ break;
989+ case BFD_RELOC_MICROBLAZE_64:
990+ microblaze_reloc = R_MICROBLAZE_IMML_64;
991+ break;
992+ case BFD_RELOC_MICROBLAZE_64_GOTPC:
993+ microblaze_reloc = R_MICROBLAZE_GOTPC_64;
994+ break;
995+ case BFD_RELOC_MICROBLAZE_64_GPC:
996+ microblaze_reloc = R_MICROBLAZE_GPC_64;
997+ break;
998+ case BFD_RELOC_MICROBLAZE_64_GOT:
999+ microblaze_reloc = R_MICROBLAZE_GOT_64;
1000+ break;
1001+ case BFD_RELOC_MICROBLAZE_64_TEXTPCREL:
1002+ microblaze_reloc = R_MICROBLAZE_TEXTPCREL_64;
1003+ break;
1004+ case BFD_RELOC_MICROBLAZE_64_TEXTREL:
1005+ microblaze_reloc = R_MICROBLAZE_TEXTREL_64;
1006+ break;
1007+ case BFD_RELOC_MICROBLAZE_64_PLT:
1008+ microblaze_reloc = R_MICROBLAZE_PLT_64;
1009+ break;
1010+ case BFD_RELOC_MICROBLAZE_64_GOTOFF:
1011+ microblaze_reloc = R_MICROBLAZE_GOTOFF_64;
1012+ break;
1013+ case BFD_RELOC_MICROBLAZE_32_GOTOFF:
1014+ microblaze_reloc = R_MICROBLAZE_GOTOFF_32;
1015+ break;
1016+ case BFD_RELOC_MICROBLAZE_64_TLSGD:
1017+ microblaze_reloc = R_MICROBLAZE_TLSGD;
1018+ break;
1019+ case BFD_RELOC_MICROBLAZE_64_TLSLD:
1020+ microblaze_reloc = R_MICROBLAZE_TLSLD;
1021+ break;
1022+ case BFD_RELOC_MICROBLAZE_32_TLSDTPREL:
1023+ microblaze_reloc = R_MICROBLAZE_TLSDTPREL32;
1024+ break;
1025+ case BFD_RELOC_MICROBLAZE_64_TLSDTPREL:
1026+ microblaze_reloc = R_MICROBLAZE_TLSDTPREL64;
1027+ break;
1028+ case BFD_RELOC_MICROBLAZE_32_TLSDTPMOD:
1029+ microblaze_reloc = R_MICROBLAZE_TLSDTPMOD32;
1030+ break;
1031+ case BFD_RELOC_MICROBLAZE_64_TLSGOTTPREL:
1032+ microblaze_reloc = R_MICROBLAZE_TLSGOTTPREL32;
1033+ break;
1034+ case BFD_RELOC_MICROBLAZE_64_TLSTPREL:
1035+ microblaze_reloc = R_MICROBLAZE_TLSTPREL32;
1036+ break;
1037+ case BFD_RELOC_MICROBLAZE_COPY:
1038+ microblaze_reloc = R_MICROBLAZE_COPY;
1039+ break;
1040+ default:
1041+ return (reloc_howto_type *) NULL;
1042+ }
1043+
1044+ if (!microblaze_elf_howto_table [R_MICROBLAZE_32])
1045+ /* Initialize howto table if needed. */
1046+ microblaze_elf_howto_init ();
1047+
1048+ return microblaze_elf_howto_table [(int) microblaze_reloc];
1049+};
1050+
1051+static reloc_howto_type *
1052+microblaze_elf_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
1053+ const char *r_name)
1054+{
1055+ unsigned int i;
1056+
1057+ for (i = 0; i < NUM_ELEM (microblaze_elf_howto_raw); i++)
1058+ if (microblaze_elf_howto_raw[i].name != NULL
1059+ && strcasecmp (microblaze_elf_howto_raw[i].name, r_name) == 0)
1060+ return &microblaze_elf_howto_raw[i];
1061+
1062+ return NULL;
1063+}
1064+
1065+/* Set the howto pointer for a RCE ELF reloc. */
1066+
1067+static bool
1068+microblaze_elf_info_to_howto (bfd * abfd,
1069+ arelent * cache_ptr,
1070+ Elf_Internal_Rela * dst)
1071+{
1072+ unsigned int r_type;
1073+
1074+ if (!microblaze_elf_howto_table [R_MICROBLAZE_32])
1075+ /* Initialize howto table if needed. */
1076+ microblaze_elf_howto_init ();
1077+
1078+ r_type = ELF64_R_TYPE (dst->r_info);
1079+ if (r_type >= R_MICROBLAZE_max)
1080+ {
1081+ /* xgettext:c-format */
1082+ _bfd_error_handler (_("%pB: unsupported relocation type %#x"),
1083+ abfd, r_type);
1084+ bfd_set_error (bfd_error_bad_value);
1085+ return false;
1086+ }
1087+
1088+ cache_ptr->howto = microblaze_elf_howto_table [r_type];
1089+ return true;
1090+}
1091+
1092+/* Relax table contains information about instructions which can
1093+ be removed by relaxation -- replacing a long address with a
1094+ short address. */
1095+struct relax_table
1096+{
1097+ /* Address where bytes may be deleted. */
1098+ bfd_vma addr;
1099+
1100+ /* Number of bytes to be deleted. */
1101+ size_t size;
1102+};
1103+
1104+struct _microblaze_elf_section_data
1105+{
1106+ struct bfd_elf_section_data elf;
1107+ /* Count of used relaxation table entries. */
1108+ size_t relax_count;
1109+ /* Relaxation table. */
1110+ struct relax_table *relax;
1111+};
1112+
1113+#define microblaze_elf_section_data(sec) \
1114+ ((struct _microblaze_elf_section_data *) elf_section_data (sec))
1115+
1116+static bool
1117+microblaze_elf_new_section_hook (bfd *abfd, asection *sec)
1118+{
1119+ if (!sec->used_by_bfd)
1120+ {
1121+ struct _microblaze_elf_section_data *sdata;
1122+ size_t amt = sizeof (*sdata);
1123+
1124+ sdata = bfd_zalloc (abfd, amt);
1125+ if (sdata == NULL)
1126+ return false;
1127+ sec->used_by_bfd = sdata;
1128+ }
1129+
1130+ return _bfd_elf_new_section_hook (abfd, sec);
1131+}
1132+
1133+/* Microblaze ELF local labels start with 'L.' or '$L', not '.L'. */
1134+
1135+static bool
1136+microblaze_elf_is_local_label_name (bfd *abfd, const char *name)
1137+{
1138+ if (name[0] == 'L' && name[1] == '.')
1139+ return true;
1140+
1141+ if (name[0] == '$' && name[1] == 'L')
1142+ return true;
1143+
1144+ /* With gcc, the labels go back to starting with '.', so we accept
1145+ the generic ELF local label syntax as well. */
1146+ return _bfd_elf_is_local_label_name (abfd, name);
1147+}
1148+
1149+/* ELF linker hash entry. */
1150+
1151+struct elf64_mb_link_hash_entry
1152+{
1153+ struct elf_link_hash_entry elf;
1154+
1155+ /* TLS Reference Types for the symbol; Updated by check_relocs */
1156+#define TLS_GD 1 /* GD reloc. */
1157+#define TLS_LD 2 /* LD reloc. */
1158+#define TLS_TPREL 4 /* TPREL reloc, => IE. */
1159+#define TLS_DTPREL 8 /* DTPREL reloc, => LD. */
1160+#define TLS_TLS 16 /* Any TLS reloc. */
1161+ unsigned char tls_mask;
1162+
1163+};
1164+
1165+#define IS_TLS_GD(x) (x == (TLS_TLS | TLS_GD))
1166+#define IS_TLS_LD(x) (x == (TLS_TLS | TLS_LD))
1167+#define IS_TLS_DTPREL(x) (x == (TLS_TLS | TLS_DTPREL))
1168+#define IS_TLS_NONE(x) (x == 0)
1169+
1170+#define elf64_mb_hash_entry(ent) ((struct elf64_mb_link_hash_entry *)(ent))
1171+
1172+/* ELF linker hash table. */
1173+
1174+struct elf64_mb_link_hash_table
1175+{
1176+ struct elf_link_hash_table elf;
1177+
1178+ /* TLS Local Dynamic GOT Entry */
1179+ union {
1180+ bfd_signed_vma refcount;
1181+ bfd_vma offset;
1182+ } tlsld_got;
1183+};
1184+
1185+/* Nonzero if this section has TLS related relocations. */
1186+#define has_tls_reloc sec_flg0
1187+
1188+/* Get the ELF linker hash table from a link_info structure. */
1189+
1190+#define elf64_mb_hash_table(p) \
1191+ ((is_elf_hash_table ((p)->hash) \
1192+ && elf_hash_table_id (elf_hash_table (p)) == MICROBLAZE_ELF_DATA) \
1193+ ? (struct elf64_mb_link_hash_table *) (p)->hash : NULL)
1194+
1195+/* Create an entry in a microblaze ELF linker hash table. */
1196+
1197+static struct bfd_hash_entry *
1198+link_hash_newfunc (struct bfd_hash_entry *entry,
1199+ struct bfd_hash_table *table,
1200+ const char *string)
1201+{
1202+ /* Allocate the structure if it has not already been allocated by a
1203+ subclass. */
1204+ if (entry == NULL)
1205+ {
1206+ entry = bfd_hash_allocate (table,
1207+ sizeof (struct elf64_mb_link_hash_entry));
1208+ if (entry == NULL)
1209+ return entry;
1210+ }
1211+
1212+ /* Call the allocation method of the superclass. */
1213+ entry = _bfd_elf_link_hash_newfunc (entry, table, string);
1214+ if (entry != NULL)
1215+ {
1216+ struct elf64_mb_link_hash_entry *eh;
1217+
1218+ eh = (struct elf64_mb_link_hash_entry *) entry;
1219+ eh->tls_mask = 0;
1220+ }
1221+
1222+ return entry;
1223+}
1224+
1225+/* Create a mb ELF linker hash table. */
1226+
1227+static struct bfd_link_hash_table *
1228+microblaze_elf_link_hash_table_create (bfd *abfd)
1229+{
1230+ struct elf64_mb_link_hash_table *ret;
1231+ size_t amt = sizeof (struct elf64_mb_link_hash_table);
1232+
1233+ ret = (struct elf64_mb_link_hash_table *) bfd_zmalloc (amt);
1234+ if (ret == NULL)
1235+ return NULL;
1236+
1237+ if (!_bfd_elf_link_hash_table_init (&ret->elf, abfd, link_hash_newfunc,
1238+ sizeof (struct elf64_mb_link_hash_entry),
1239+ MICROBLAZE_ELF_DATA))
1240+ {
1241+ free (ret);
1242+ return NULL;
1243+ }
1244+
1245+ return &ret->elf.root;
1246+}
1247+
1248+/* Set the values of the small data pointers. */
1249+
1250+static void
1251+microblaze_elf_final_sdp (struct bfd_link_info *info)
1252+{
1253+ struct bfd_link_hash_entry *h;
1254+
1255+ h = bfd_link_hash_lookup (info->hash, RO_SDA_ANCHOR_NAME, false, false, true);
1256+ if (h != (struct bfd_link_hash_entry *) NULL
1257+ && h->type == bfd_link_hash_defined)
1258+ ro_small_data_pointer = (h->u.def.value
1259+ + h->u.def.section->output_section->vma
1260+ + h->u.def.section->output_offset);
1261+
1262+ h = bfd_link_hash_lookup (info->hash, RW_SDA_ANCHOR_NAME, false, false, true);
1263+ if (h != (struct bfd_link_hash_entry *) NULL
1264+ && h->type == bfd_link_hash_defined)
1265+ rw_small_data_pointer = (h->u.def.value
1266+ + h->u.def.section->output_section->vma
1267+ + h->u.def.section->output_offset);
1268+}
1269+
1270+static bfd_vma
1271+dtprel_base (struct bfd_link_info *info)
1272+{
1273+ /* If tls_sec is NULL, we should have signalled an error already. */
1274+ if (elf_hash_table (info)->tls_sec == NULL)
1275+ return 0;
1276+ return elf_hash_table (info)->tls_sec->vma;
1277+}
1278+
1279+/* The size of the thread control block. */
1280+#define TCB_SIZE 8
1281+
1282+/* Output a simple dynamic relocation into SRELOC. */
1283+
1284+static void
1285+microblaze_elf_output_dynamic_relocation (bfd *output_bfd,
1286+ asection *sreloc,
1287+ unsigned long reloc_index,
1288+ unsigned long indx,
1289+ int r_type,
1290+ bfd_vma offset,
1291+ bfd_vma addend)
1292+{
1293+
1294+ Elf_Internal_Rela rel;
1295+
1296+ rel.r_info = ELF64_R_INFO (indx, r_type);
1297+ rel.r_offset = offset;
1298+ rel.r_addend = addend;
1299+
1300+ bfd_elf64_swap_reloca_out (output_bfd, &rel,
1301+ (sreloc->contents + reloc_index * sizeof (Elf64_External_Rela)));
1302+}
1303+
1304+/* This code is taken from elf64-m32r.c
1305+ There is some attempt to make this function usable for many architectures,
1306+ both USE_REL and USE_RELA ['twould be nice if such a critter existed],
1307+ if only to serve as a learning tool.
1308+
1309+ The RELOCATE_SECTION function is called by the new ELF backend linker
1310+ to handle the relocations for a section.
1311+
1312+ The relocs are always passed as Rela structures; if the section
1313+ actually uses Rel structures, the r_addend field will always be
1314+ zero.
1315+
1316+ This function is responsible for adjust the section contents as
1317+ necessary, and (if using Rela relocs and generating a
1318+ relocatable output file) adjusting the reloc addend as
1319+ necessary.
1320+
1321+ This function does not have to worry about setting the reloc
1322+ address or the reloc symbol index.
1323+
1324+ LOCAL_SYMS is a pointer to the swapped in local symbols.
1325+
1326+ LOCAL_SECTIONS is an array giving the section in the input file
1327+ corresponding to the st_shndx field of each local symbol.
1328+
1329+ The global hash table entry for the global symbols can be found
1330+ via elf_sym_hashes (input_bfd).
1331+
1332+ When generating relocatable output, this function must handle
1333+ STB_LOCAL/STT_SECTION symbols specially. The output symbol is
1334+ going to be the section symbol corresponding to the output
1335+ section, which means that the addend must be adjusted
1336+ accordingly. */
1337+
1338+static int
1339+microblaze_elf_relocate_section (bfd *output_bfd,
1340+ struct bfd_link_info *info,
1341+ bfd *input_bfd,
1342+ asection *input_section,
1343+ bfd_byte *contents,
1344+ Elf_Internal_Rela *relocs,
1345+ Elf_Internal_Sym *local_syms,
1346+ asection **local_sections)
1347+{
1348+ struct elf64_mb_link_hash_table *htab;
1349+ Elf_Internal_Shdr *symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr;
1350+ struct elf_link_hash_entry **sym_hashes = elf_sym_hashes (input_bfd);
1351+ Elf_Internal_Rela *rel, *relend;
1352+ int endian = (bfd_little_endian (output_bfd)) ? 0 : 2;
1353+ /* Assume success. */
1354+ bool ret = true;
1355+ asection *sreloc;
1356+ bfd_vma *local_got_offsets;
1357+ unsigned int tls_type;
1358+
1359+ if (!microblaze_elf_howto_table[R_MICROBLAZE_max-1])
1360+ microblaze_elf_howto_init ();
1361+
1362+ htab = elf64_mb_hash_table (info);
1363+ if (htab == NULL)
1364+ return false;
1365+
1366+ local_got_offsets = elf_local_got_offsets (input_bfd);
1367+
1368+ sreloc = elf_section_data (input_section)->sreloc;
1369+
1370+ rel = relocs;
1371+ relend = relocs + input_section->reloc_count;
1372+ for (; rel < relend; rel++)
1373+ {
1374+ int r_type;
1375+ reloc_howto_type *howto;
1376+ unsigned long r_symndx;
1377+ bfd_vma addend = rel->r_addend;
1378+ bfd_vma offset = rel->r_offset;
1379+ struct elf_link_hash_entry *h;
1380+ Elf_Internal_Sym *sym;
1381+ asection *sec;
1382+ const char *sym_name;
1383+ bfd_reloc_status_type r = bfd_reloc_ok;
1384+ const char *errmsg = NULL;
1385+ bool unresolved_reloc = false;
1386+
1387+ h = NULL;
1388+ r_type = ELF64_R_TYPE (rel->r_info);
1389+ tls_type = 0;
1390+
1391+ if (r_type < 0 || r_type >= (int) R_MICROBLAZE_max)
1392+ {
1393+ /* xgettext:c-format */
1394+ _bfd_error_handler (_("%pB: unsupported relocation type %#x"),
1395+ input_bfd, (int) r_type);
1396+ bfd_set_error (bfd_error_bad_value);
1397+ ret = false;
1398+ continue;
1399+ }
1400+
1401+ howto = microblaze_elf_howto_table[r_type];
1402+ r_symndx = ELF64_R_SYM (rel->r_info);
1403+
1404+ if (bfd_link_relocatable (info))
1405+ {
1406+ /* This is a relocatable link. We don't have to change
1407+ anything, unless the reloc is against a section symbol,
1408+ in which case we have to adjust according to where the
1409+ section symbol winds up in the output section. */
1410+ sec = NULL;
1411+ if (r_symndx >= symtab_hdr->sh_info)
1412+ /* External symbol. */
1413+ continue;
1414+
1415+ /* Local symbol. */
1416+ sym = local_syms + r_symndx;
1417+ sym_name = "<local symbol>";
1418+ /* STT_SECTION: symbol is associated with a section. */
1419+ if (ELF_ST_TYPE (sym->st_info) != STT_SECTION)
1420+ /* Symbol isn't associated with a section. Nothing to do. */
1421+ continue;
1422+
1423+ sec = local_sections[r_symndx];
1424+ addend += sec->output_offset + sym->st_value;
1425+#ifndef USE_REL
1426+ /* This can't be done for USE_REL because it doesn't mean anything
1427+ and elf_link_input_bfd asserts this stays zero. */
1428+ /* rel->r_addend = addend; */
1429+#endif
1430+
1431+#ifndef USE_REL
1432+ /* Addends are stored with relocs. We're done. */
1433+ continue;
1434+#else /* USE_REL */
1435+ /* If partial_inplace, we need to store any additional addend
1436+ back in the section. */
1437+ if (!howto->partial_inplace)
1438+ continue;
1439+ /* ??? Here is a nice place to call a special_function like handler. */
1440+ r = _bfd_relocate_contents (howto, input_bfd, addend,
1441+ contents + offset);
1442+#endif /* USE_REL */
1443+ }
1444+ else
1445+ {
1446+ bfd_vma relocation;
1447+ bool resolved_to_zero;
1448+
1449+ /* This is a final link. */
1450+ sym = NULL;
1451+ sec = NULL;
1452+ unresolved_reloc = false;
1453+
1454+ if (r_symndx < symtab_hdr->sh_info)
1455+ {
1456+ /* Local symbol. */
1457+ sym = local_syms + r_symndx;
1458+ sec = local_sections[r_symndx];
1459+ if (sec == 0)
1460+ continue;
1461+ sym_name = "<local symbol>";
1462+ relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
1463+ /* r_addend may have changed if the reference section was
1464+ a merge section. */
1465+ addend = rel->r_addend;
1466+ }
1467+ else
1468+ {
1469+ /* External symbol. */
1470+ bool warned ATTRIBUTE_UNUSED;
1471+ bool ignored ATTRIBUTE_UNUSED;
1472+
1473+ RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
1474+ r_symndx, symtab_hdr, sym_hashes,
1475+ h, sec, relocation,
1476+ unresolved_reloc, warned, ignored);
1477+ sym_name = h->root.root.string;
1478+ }
1479+
1480+ /* Sanity check the address. */
1481+ if (offset > bfd_get_section_limit (input_bfd, input_section))
1482+ {
1483+ r = bfd_reloc_outofrange;
1484+ goto check_reloc;
1485+ }
1486+
1487+ resolved_to_zero = (h != NULL
1488+ && UNDEFWEAK_NO_DYNAMIC_RELOC (info, h));
1489+
1490+ switch ((int) r_type)
1491+ {
1492+ case (int) R_MICROBLAZE_SRO32 :
1493+ {
1494+ const char *name;
1495+
1496+ /* Only relocate if the symbol is defined. */
1497+ if (sec)
1498+ {
1499+ name = bfd_section_name (sec);
1500+
1501+ if (strcmp (name, ".sdata2") == 0
1502+ || strcmp (name, ".sbss2") == 0)
1503+ {
1504+ if (ro_small_data_pointer == 0)
1505+ microblaze_elf_final_sdp (info);
1506+ if (ro_small_data_pointer == 0)
1507+ {
1508+ ret = false;
1509+ r = bfd_reloc_undefined;
1510+ goto check_reloc;
1511+ }
1512+
1513+ /* At this point `relocation' contains the object's
1514+ address. */
1515+ relocation -= ro_small_data_pointer;
1516+ /* Now it contains the offset from _SDA2_BASE_. */
1517+ r = _bfd_final_link_relocate (howto, input_bfd,
1518+ input_section,
1519+ contents, offset,
1520+ relocation, addend);
1521+ }
1522+ else
1523+ {
1524+ _bfd_error_handler
1525+ /* xgettext:c-format */
1526+ (_("%pB: the target (%s) of an %s relocation"
1527+ " is in the wrong section (%pA)"),
1528+ input_bfd,
1529+ sym_name,
1530+ microblaze_elf_howto_table[(int) r_type]->name,
1531+ sec);
1532+ /*bfd_set_error (bfd_error_bad_value); ??? why? */
1533+ ret = false;
1534+ continue;
1535+ }
1536+ }
1537+ }
1538+ break;
1539+
1540+ case (int) R_MICROBLAZE_SRW32 :
1541+ {
1542+ const char *name;
1543+
1544+ /* Only relocate if the symbol is defined. */
1545+ if (sec)
1546+ {
1547+ name = bfd_section_name (sec);
1548+
1549+ if (strcmp (name, ".sdata") == 0
1550+ || strcmp (name, ".sbss") == 0)
1551+ {
1552+ if (rw_small_data_pointer == 0)
1553+ microblaze_elf_final_sdp (info);
1554+ if (rw_small_data_pointer == 0)
1555+ {
1556+ ret = false;
1557+ r = bfd_reloc_undefined;
1558+ goto check_reloc;
1559+ }
1560+
1561+ /* At this point `relocation' contains the object's
1562+ address. */
1563+ relocation -= rw_small_data_pointer;
1564+ /* Now it contains the offset from _SDA_BASE_. */
1565+ r = _bfd_final_link_relocate (howto, input_bfd,
1566+ input_section,
1567+ contents, offset,
1568+ relocation, addend);
1569+ }
1570+ else
1571+ {
1572+ _bfd_error_handler
1573+ /* xgettext:c-format */
1574+ (_("%pB: the target (%s) of an %s relocation"
1575+ " is in the wrong section (%pA)"),
1576+ input_bfd,
1577+ sym_name,
1578+ microblaze_elf_howto_table[(int) r_type]->name,
1579+ sec);
1580+ /*bfd_set_error (bfd_error_bad_value); ??? why? */
1581+ ret = false;
1582+ continue;
1583+ }
1584+ }
1585+ }
1586+ break;
1587+
1588+ case (int) R_MICROBLAZE_32_SYM_OP_SYM:
1589+ break; /* Do nothing. */
1590+
1591+ case (int) R_MICROBLAZE_GOTPC_64:
1592+ relocation = (htab->elf.sgotplt->output_section->vma
1593+ + htab->elf.sgotplt->output_offset);
1594+ relocation -= (input_section->output_section->vma
1595+ + input_section->output_offset
1596+ + offset + INST_WORD_SIZE);
1597+ relocation += addend;
1598+ bfd_put_16 (input_bfd, (relocation >> 16) & 0xffff,
1599+ contents + offset + endian);
1600+ bfd_put_16 (input_bfd, relocation & 0xffff,
1601+ contents + offset + endian + INST_WORD_SIZE);
1602+ break;
1603+
1604+ case (int) R_MICROBLAZE_TEXTPCREL_64:
1605+ relocation = input_section->output_section->vma;
1606+ relocation -= (input_section->output_section->vma
1607+ + input_section->output_offset
1608+ + offset + INST_WORD_SIZE);
1609+ relocation += addend;
1610+ bfd_put_16 (input_bfd, (relocation >> 16) & 0xffff,
1611+ contents + offset + endian);
1612+ bfd_put_16 (input_bfd, relocation & 0xffff,
1613+ contents + offset + endian + INST_WORD_SIZE);
1614+ break;
1615+
1616+ case (int) R_MICROBLAZE_PLT_64:
1617+ {
1618+ bfd_vma immediate;
1619+ if (htab->elf.splt != NULL && h != NULL
1620+ && h->plt.offset != (bfd_vma) -1)
1621+ {
1622+ relocation = (htab->elf.splt->output_section->vma
1623+ + htab->elf.splt->output_offset
1624+ + h->plt.offset);
1625+ unresolved_reloc = false;
1626+ immediate = relocation - (input_section->output_section->vma
1627+ + input_section->output_offset
1628+ + offset + INST_WORD_SIZE);
1629+ bfd_put_16 (input_bfd, (immediate >> 16) & 0xffff,
1630+ contents + offset + endian);
1631+ bfd_put_16 (input_bfd, immediate & 0xffff,
1632+ contents + offset + endian + INST_WORD_SIZE);
1633+ }
1634+ else
1635+ {
1636+ relocation -= (input_section->output_section->vma
1637+ + input_section->output_offset
1638+ + offset + INST_WORD_SIZE);
1639+ immediate = relocation;
1640+ bfd_put_16 (input_bfd, (immediate >> 16) & 0xffff,
1641+ contents + offset + endian);
1642+ bfd_put_16 (input_bfd, immediate & 0xffff,
1643+ contents + offset + endian + INST_WORD_SIZE);
1644+ }
1645+ break;
1646+ }
1647+
1648+ case (int) R_MICROBLAZE_TLSGD:
1649+ tls_type = (TLS_TLS | TLS_GD);
1650+ goto dogot;
1651+ case (int) R_MICROBLAZE_TLSLD:
1652+ tls_type = (TLS_TLS | TLS_LD);
1653+ /* Fall through. */
1654+ dogot:
1655+ case (int) R_MICROBLAZE_GOT_64:
1656+ {
1657+ bfd_vma *offp;
1658+ bfd_vma off, off2;
1659+ unsigned long indx;
1660+ bfd_vma static_value;
1661+
1662+ bool need_relocs = false;
1663+ if (htab->elf.sgot == NULL)
1664+ abort ();
1665+
1666+ indx = 0;
1667+ offp = NULL;
1668+
1669+ /* 1. Identify GOT Offset;
1670+ 2. Compute Static Values
1671+ 3. Process Module Id, Process Offset
1672+ 4. Fixup Relocation with GOT offset value. */
1673+
1674+ /* 1. Determine GOT Offset to use : TLS_LD, global, local */
1675+ if (IS_TLS_LD (tls_type))
1676+ offp = &htab->tlsld_got.offset;
1677+ else if (h != NULL)
1678+ {
1679+ if (htab->elf.sgotplt != NULL
1680+ && h->got.offset != (bfd_vma) -1)
1681+ offp = &h->got.offset;
1682+ else
1683+ abort ();
1684+ }
1685+ else
1686+ {
1687+ if (local_got_offsets == NULL)
1688+ abort ();
1689+ offp = &local_got_offsets[r_symndx];
1690+ }
1691+
1692+ if (!offp)
1693+ abort ();
1694+
1695+ off = (*offp) & ~1;
1696+ off2 = off;
1697+
1698+ if (IS_TLS_LD(tls_type) || IS_TLS_GD(tls_type))
1699+ off2 = off + 4;
1700+
1701+ /* Symbol index to use for relocs */
1702+ if (h != NULL)
1703+ {
1704+ bool dyn =
1705+ elf_hash_table (info)->dynamic_sections_created;
1706+
1707+ if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn,
1708+ bfd_link_pic (info),
1709+ h)
1710+ && (!bfd_link_pic (info)
1711+ || !SYMBOL_REFERENCES_LOCAL (info, h)))
1712+ indx = h->dynindx;
1713+ }
1714+
1715+ /* Need to generate relocs ? */
1716+ if ((bfd_link_pic (info) || indx != 0)
1717+ && (h == NULL
1718+ || (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
1719+ && !resolved_to_zero)
1720+ || h->root.type != bfd_link_hash_undefweak))
1721+ need_relocs = true;
1722+
1723+ /* 2. Compute/Emit Static value of r-expression */
1724+ static_value = relocation + addend;
1725+
1726+ /* 3. Process module-id and offset */
1727+ if (! ((*offp) & 1) )
1728+ {
1729+ bfd_vma got_offset;
1730+
1731+ got_offset = (htab->elf.sgot->output_section->vma
1732+ + htab->elf.sgot->output_offset
1733+ + off);
1734+
1735+ /* Process module-id */
1736+ if (IS_TLS_LD(tls_type))
1737+ {
1738+ if (! bfd_link_pic (info))
1739+ bfd_put_32 (output_bfd, 1,
1740+ htab->elf.sgot->contents + off);
1741+ else
1742+ microblaze_elf_output_dynamic_relocation
1743+ (output_bfd,
1744+ htab->elf.srelgot,
1745+ htab->elf.srelgot->reloc_count++,
1746+ /* symindex= */ 0, R_MICROBLAZE_TLSDTPMOD32,
1747+ got_offset, 0);
1748+ }
1749+ else if (IS_TLS_GD(tls_type))
1750+ {
1751+ if (! need_relocs)
1752+ bfd_put_32 (output_bfd, 1,
1753+ htab->elf.sgot->contents + off);
1754+ else
1755+ microblaze_elf_output_dynamic_relocation
1756+ (output_bfd,
1757+ htab->elf.srelgot,
1758+ htab->elf.srelgot->reloc_count++,
1759+ /* symindex= */ indx, R_MICROBLAZE_TLSDTPMOD32,
1760+ got_offset, indx ? 0 : static_value);
1761+ }
1762+
1763+ /* Process Offset */
1764+ if (htab->elf.srelgot == NULL)
1765+ abort ();
1766+
1767+ got_offset = (htab->elf.sgot->output_section->vma
1768+ + htab->elf.sgot->output_offset
1769+ + off2);
1770+ if (IS_TLS_LD(tls_type))
1771+ {
1772+ /* For LD, offset should be 0 */
1773+ *offp |= 1;
1774+ bfd_put_32 (output_bfd, 0,
1775+ htab->elf.sgot->contents + off2);
1776+ }
1777+ else if (IS_TLS_GD(tls_type))
1778+ {
1779+ *offp |= 1;
1780+ static_value -= dtprel_base(info);
1781+ if (need_relocs)
1782+ microblaze_elf_output_dynamic_relocation
1783+ (output_bfd,
1784+ htab->elf.srelgot,
1785+ htab->elf.srelgot->reloc_count++,
1786+ /* symindex= */ indx, R_MICROBLAZE_TLSDTPREL32,
1787+ got_offset, indx ? 0 : static_value);
1788+ else
1789+ bfd_put_32 (output_bfd, static_value,
1790+ htab->elf.sgot->contents + off2);
1791+ }
1792+ else
1793+ {
1794+ bfd_put_32 (output_bfd, static_value,
1795+ htab->elf.sgot->contents + off2);
1796+
1797+ /* Relocs for dyn symbols generated by
1798+ finish_dynamic_symbols */
1799+ if (bfd_link_pic (info) && h == NULL)
1800+ {
1801+ *offp |= 1;
1802+ microblaze_elf_output_dynamic_relocation
1803+ (output_bfd,
1804+ htab->elf.srelgot,
1805+ htab->elf.srelgot->reloc_count++,
1806+ /* symindex= */ indx, R_MICROBLAZE_REL,
1807+ got_offset, static_value);
1808+ }
1809+ }
1810+ }
1811+
1812+ /* 4. Fixup Relocation with GOT offset value
1813+ Compute relative address of GOT entry for applying
1814+ the current relocation */
1815+ relocation = htab->elf.sgot->output_section->vma
1816+ + htab->elf.sgot->output_offset
1817+ + off
1818+ - htab->elf.sgotplt->output_section->vma
1819+ - htab->elf.sgotplt->output_offset;
1820+
1821+ /* Apply Current Relocation */
1822+ bfd_put_16 (input_bfd, (relocation >> 16) & 0xffff,
1823+ contents + offset + endian);
1824+ bfd_put_16 (input_bfd, relocation & 0xffff,
1825+ contents + offset + endian + INST_WORD_SIZE);
1826+
1827+ unresolved_reloc = false;
1828+ break;
1829+ }
1830+
1831+ case (int) R_MICROBLAZE_GOTOFF_64:
1832+ {
1833+ bfd_vma immediate;
1834+ unsigned short lo, high;
1835+ relocation += addend;
1836+ relocation -= (htab->elf.sgotplt->output_section->vma
1837+ + htab->elf.sgotplt->output_offset);
1838+ /* Write this value into correct location. */
1839+ immediate = relocation;
1840+ lo = immediate & 0x0000ffff;
1841+ high = (immediate >> 16) & 0x0000ffff;
1842+ bfd_put_16 (input_bfd, high, contents + offset + endian);
1843+ bfd_put_16 (input_bfd, lo,
1844+ contents + offset + INST_WORD_SIZE + endian);
1845+ break;
1846+ }
1847+
1848+ case (int) R_MICROBLAZE_GOTOFF_32:
1849+ {
1850+ relocation += addend;
1851+ relocation -= (htab->elf.sgotplt->output_section->vma
1852+ + htab->elf.sgotplt->output_offset);
1853+ /* Write this value into correct location. */
1854+ bfd_put_32 (input_bfd, relocation, contents + offset);
1855+ break;
1856+ }
1857+
1858+ case (int) R_MICROBLAZE_TLSDTPREL64:
1859+ relocation += addend;
1860+ relocation -= dtprel_base(info);
1861+ bfd_put_16 (input_bfd, (relocation >> 16) & 0xffff,
1862+ contents + offset + endian);
1863+ bfd_put_16 (input_bfd, relocation & 0xffff,
1864+ contents + offset + endian + INST_WORD_SIZE);
1865+ break;
1866+ case (int) R_MICROBLAZE_TEXTREL_64:
1867+ case (int) R_MICROBLAZE_TEXTREL_32_LO:
1868+ case (int) R_MICROBLAZE_64_PCREL :
1869+ case (int) R_MICROBLAZE_64:
1870+ case (int) R_MICROBLAZE_32:
1871+ {
1872+ /* r_symndx will be STN_UNDEF (zero) only for relocs against symbols
1873+ from removed linkonce sections, or sections discarded by
1874+ a linker script. */
1875+ if (r_symndx == STN_UNDEF || (input_section->flags & SEC_ALLOC) == 0)
1876+ {
1877+ relocation += addend;
1878+ if (r_type == R_MICROBLAZE_32)// || r_type == R_MICROBLAZE_IMML_64)
1879+ bfd_put_32 (input_bfd, relocation, contents + offset);
1880+ else
1881+ {
1882+ if (r_type == R_MICROBLAZE_64_PCREL)
1883+ relocation -= (input_section->output_section->vma
1884+ + input_section->output_offset
1885+ + offset + INST_WORD_SIZE);
1886+ else if (r_type == R_MICROBLAZE_TEXTREL_64
1887+ || r_type == R_MICROBLAZE_TEXTREL_32_LO)
1888+ relocation -= input_section->output_section->vma;
1889+
1890+ if (r_type == R_MICROBLAZE_TEXTREL_32_LO)
1891+ bfd_put_16 (input_bfd, relocation & 0xffff,
1892+ contents + offset + endian);
1893+
1894+ else
1895+ {
1896+ bfd_put_16 (input_bfd, (relocation >> 16) & 0xffff,
1897+ contents + offset + endian);
1898+ bfd_put_16 (input_bfd, relocation & 0xffff,
1899+ contents + offset + endian + INST_WORD_SIZE);
1900+ }
1901+ }
1902+ break;
1903+ }
1904+
1905+ if ((bfd_link_pic (info)
1906+ && (h == NULL
1907+ || (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
1908+ && !resolved_to_zero)
1909+ || h->root.type != bfd_link_hash_undefweak)
1910+ && (!howto->pc_relative
1911+ || (h != NULL
1912+ && h->dynindx != -1
1913+ && (!info->symbolic
1914+ || !h->def_regular))))
1915+ || (!bfd_link_pic (info)
1916+ && h != NULL
1917+ && h->dynindx != -1
1918+ && !h->non_got_ref
1919+ && ((h->def_dynamic
1920+ && !h->def_regular)
1921+ || h->root.type == bfd_link_hash_undefweak
1922+ || h->root.type == bfd_link_hash_undefined)))
1923+ {
1924+ Elf_Internal_Rela outrel;
1925+ bfd_byte *loc;
1926+ bool skip;
1927+
1928+ /* When generating a shared object, these relocations
1929+ are copied into the output file to be resolved at run
1930+ time. */
1931+
1932+ BFD_ASSERT (sreloc != NULL);
1933+
1934+ skip = false;
1935+
1936+ outrel.r_offset =
1937+ _bfd_elf_section_offset (output_bfd, info, input_section,
1938+ rel->r_offset);
1939+ if (outrel.r_offset == (bfd_vma) -1)
1940+ skip = true;
1941+ else if (outrel.r_offset == (bfd_vma) -2)
1942+ skip = true;
1943+ outrel.r_offset += (input_section->output_section->vma
1944+ + input_section->output_offset);
1945+
1946+ if (skip)
1947+ memset (&outrel, 0, sizeof outrel);
1948+ /* h->dynindx may be -1 if the symbol was marked to
1949+ become local. */
1950+ else if (h != NULL
1951+ && ((! info->symbolic && h->dynindx != -1)
1952+ || !h->def_regular))
1953+ {
1954+ BFD_ASSERT (h->dynindx != -1);
1955+ outrel.r_info = ELF64_R_INFO (h->dynindx, r_type);
1956+ outrel.r_addend = addend;
1957+ }
1958+ else
1959+ {
1960+ if (r_type == R_MICROBLAZE_32)
1961+ {
1962+ outrel.r_info = ELF64_R_INFO (0, R_MICROBLAZE_REL);
1963+ outrel.r_addend = relocation + addend;
1964+ }
1965+ else
1966+ {
1967+ BFD_FAIL ();
1968+ _bfd_error_handler
1969+ (_("%pB: probably compiled without -fPIC?"),
1970+ input_bfd);
1971+ bfd_set_error (bfd_error_bad_value);
1972+ return false;
1973+ }
1974+ }
1975+
1976+ loc = sreloc->contents;
1977+ loc += sreloc->reloc_count++ * sizeof (Elf64_External_Rela);
1978+ bfd_elf64_swap_reloca_out (output_bfd, &outrel, loc);
1979+ break;
1980+ }
1981+ else
1982+ {
1983+ relocation += addend;
1984+ if (r_type == R_MICROBLAZE_32)
1985+ bfd_put_32 (input_bfd, relocation, contents + offset);
1986+ else
1987+ {
1988+ if (r_type == R_MICROBLAZE_64_PCREL)
1989+ relocation -= (input_section->output_section->vma
1990+ + input_section->output_offset
1991+ + offset + INST_WORD_SIZE);
1992+ else if (r_type == R_MICROBLAZE_TEXTREL_64
1993+ || r_type == R_MICROBLAZE_TEXTREL_32_LO)
1994+ relocation -= input_section->output_section->vma;
1995+
1996+ if (r_type == R_MICROBLAZE_TEXTREL_32_LO)
1997+ {
1998+ bfd_put_16 (input_bfd, relocation & 0xffff,
1999+ contents + offset + endian);
2000+ }
2001+ else
2002+ {
2003+ bfd_put_16 (input_bfd, (relocation >> 16) & 0xffff,
2004+ contents + offset + endian);
2005+ bfd_put_16 (input_bfd, relocation & 0xffff,
2006+ contents + offset + endian
2007+ + INST_WORD_SIZE);
2008+ }
2009+ }
2010+ break;
2011+ }
2012+ }
2013+
2014+ default :
2015+ r = _bfd_final_link_relocate (howto, input_bfd, input_section,
2016+ contents, offset,
2017+ relocation, addend);
2018+ break;
2019+ }
2020+ }
2021+
2022+ check_reloc:
2023+
2024+ if (r != bfd_reloc_ok)
2025+ {
2026+ /* FIXME: This should be generic enough to go in a utility. */
2027+ const char *name;
2028+
2029+ if (h != NULL)
2030+ name = h->root.root.string;
2031+ else
2032+ {
2033+ name = (bfd_elf_string_from_elf_section
2034+ (input_bfd, symtab_hdr->sh_link, sym->st_name));
2035+ if (name == NULL || *name == '\0')
2036+ name = bfd_section_name (sec);
2037+ }
2038+
2039+ if (errmsg != NULL)
2040+ goto common_error;
2041+
2042+ switch (r)
2043+ {
2044+ case bfd_reloc_overflow:
2045+ (*info->callbacks->reloc_overflow)
2046+ (info, (h ? &h->root : NULL), name, howto->name,
2047+ (bfd_vma) 0, input_bfd, input_section, offset);
2048+ break;
2049+
2050+ case bfd_reloc_undefined:
2051+ (*info->callbacks->undefined_symbol)
2052+ (info, name, input_bfd, input_section, offset, true);
2053+ break;
2054+
2055+ case bfd_reloc_outofrange:
2056+ errmsg = _("internal error: out of range error");
2057+ goto common_error;
2058+
2059+ case bfd_reloc_notsupported:
2060+ errmsg = _("internal error: unsupported relocation error");
2061+ goto common_error;
2062+
2063+ case bfd_reloc_dangerous:
2064+ errmsg = _("internal error: dangerous error");
2065+ goto common_error;
2066+
2067+ default:
2068+ errmsg = _("internal error: unknown error");
2069+ /* Fall through. */
2070+ common_error:
2071+ (*info->callbacks->warning) (info, errmsg, name, input_bfd,
2072+ input_section, offset);
2073+ break;
2074+ }
2075+ }
2076+ }
2077+
2078+ return ret;
2079+}
2080+
2081+/* Calculate fixup value for reference. */
2082+
2083+static size_t
2084+calc_fixup (bfd_vma start, bfd_vma size, asection *sec)
2085+{
2086+ bfd_vma end = start + size;
2087+ size_t i, fixup = 0;
2088+ struct _microblaze_elf_section_data *sdata;
2089+
2090+ if (sec == NULL || (sdata = microblaze_elf_section_data (sec)) == NULL)
2091+ return 0;
2092+
2093+ /* Look for addr in relax table, total fixup value. */
2094+ for (i = 0; i < sdata->relax_count; i++)
2095+ {
2096+ if (end <= sdata->relax[i].addr)
2097+ break;
2098+ if (end != start && start > sdata->relax[i].addr)
2099+ continue;
2100+ fixup += sdata->relax[i].size;
2101+ }
2102+ return fixup;
2103+}
2104+
2105+/* Read-modify-write into the bfd, an immediate value into appropriate fields of
2106+ a 32-bit instruction. */
2107+static void
2108+microblaze_bfd_write_imm_value_32 (bfd *abfd, bfd_byte *bfd_addr, bfd_vma val)
2109+{
2110+ unsigned long instr = bfd_get_32 (abfd, bfd_addr);
2111+ instr &= ~0x0000ffff;
2112+ instr |= (val & 0x0000ffff);
2113+ bfd_put_32 (abfd, instr, bfd_addr);
2114+}
2115+
2116+/* Read-modify-write into the bfd, an immediate value into appropriate fields of
2117+ two consecutive 32-bit instructions. */
2118+static void
2119+microblaze_bfd_write_imm_value_64 (bfd *abfd, bfd_byte *bfd_addr, bfd_vma val)
2120+{
2121+ unsigned long instr_hi;
2122+ unsigned long instr_lo;
2123+
2124+ instr_hi = bfd_get_32 (abfd, bfd_addr);
2125+ instr_hi &= ~0x0000ffff;
2126+ instr_hi |= ((val >> 16) & 0x0000ffff);
2127+ bfd_put_32 (abfd, instr_hi, bfd_addr);
2128+
2129+ instr_lo = bfd_get_32 (abfd, bfd_addr + INST_WORD_SIZE);
2130+ instr_lo &= ~0x0000ffff;
2131+ instr_lo |= (val & 0x0000ffff);
2132+ bfd_put_32 (abfd, instr_lo, bfd_addr + INST_WORD_SIZE);
2133+}
2134+
2135+static bool
2136+microblaze_elf_relax_section (bfd *abfd,
2137+ asection *sec,
2138+ struct bfd_link_info *link_info,
2139+ bool *again)
2140+{
2141+ Elf_Internal_Shdr *symtab_hdr;
2142+ Elf_Internal_Rela *internal_relocs;
2143+ Elf_Internal_Rela *free_relocs = NULL;
2144+ Elf_Internal_Rela *irel, *irelend;
2145+ bfd_byte *contents = NULL;
2146+ bfd_byte *free_contents = NULL;
2147+ int rel_count;
2148+ unsigned int shndx;
2149+ size_t i, sym_index;
2150+ asection *o;
2151+ struct elf_link_hash_entry *sym_hash;
2152+ Elf_Internal_Sym *isymbuf, *isymend;
2153+ Elf_Internal_Sym *isym;
2154+ size_t symcount;
2155+ size_t offset;
2156+ bfd_vma src, dest;
2157+ struct _microblaze_elf_section_data *sdata;
2158+
2159+ /* We only do this once per section. We may be able to delete some code
2160+ by running multiple passes, but it is not worth it. */
2161+ *again = false;
2162+
2163+ /* Only do this for a text section. */
2164+ if (bfd_link_relocatable (link_info)
2165+ || (sec->flags & SEC_RELOC) == 0
2166+ || (sec->flags & SEC_CODE) == 0
2167+ || sec->reloc_count == 0
2168+ || (sdata = microblaze_elf_section_data (sec)) == NULL)
2169+ return true;
2170+
2171+ BFD_ASSERT ((sec->size > 0) || (sec->rawsize > 0));
2172+
2173+ /* If this is the first time we have been called for this section,
2174+ initialize the cooked size. */
2175+ if (sec->size == 0)
2176+ sec->size = sec->rawsize;
2177+
2178+ /* Get symbols for this section. */
2179+ symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
2180+ isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
2181+ symcount = symtab_hdr->sh_size / sizeof (Elf64_External_Sym);
2182+ if (isymbuf == NULL)
2183+ isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr, symcount,
2184+ 0, NULL, NULL, NULL);
2185+ BFD_ASSERT (isymbuf != NULL);
2186+
2187+ internal_relocs = _bfd_elf_link_read_relocs (abfd, sec, NULL, NULL, link_info->keep_memory);
2188+ if (internal_relocs == NULL)
2189+ goto error_return;
2190+ if (! link_info->keep_memory)
2191+ free_relocs = internal_relocs;
2192+
2193+ sdata->relax_count = 0;
2194+ sdata->relax = (struct relax_table *) bfd_malloc ((sec->reloc_count + 1)
2195+ * sizeof (*sdata->relax));
2196+ if (sdata->relax == NULL)
2197+ goto error_return;
2198+
2199+ irelend = internal_relocs + sec->reloc_count;
2200+ rel_count = 0;
2201+ for (irel = internal_relocs; irel < irelend; irel++, rel_count++)
2202+ {
2203+ bfd_vma symval;
2204+ if ((ELF64_R_TYPE (irel->r_info) != (int) R_MICROBLAZE_64_PCREL)
2205+ && (ELF64_R_TYPE (irel->r_info) != (int) R_MICROBLAZE_64 )
2206+&& (ELF64_R_TYPE (irel->r_info) != (int) R_MICROBLAZE_TEXTREL_64))
2207+ continue; /* Can't delete this reloc. */
2208+
2209+ /* Get the section contents. */
2210+ if (contents == NULL)
2211+ {
2212+ if (elf_section_data (sec)->this_hdr.contents != NULL)
2213+ contents = elf_section_data (sec)->this_hdr.contents;
2214+ else
2215+ {
2216+ contents = (bfd_byte *) bfd_malloc (sec->size);
2217+ if (contents == NULL)
2218+ goto error_return;
2219+ free_contents = contents;
2220+
2221+ if (!bfd_get_section_contents (abfd, sec, contents,
2222+ (file_ptr) 0, sec->size))
2223+ goto error_return;
2224+ elf_section_data (sec)->this_hdr.contents = contents;
2225+ }
2226+ }
2227+
2228+ /* Get the value of the symbol referred to by the reloc. */
2229+ if (ELF64_R_SYM (irel->r_info) < symtab_hdr->sh_info)
2230+ {
2231+ /* A local symbol. */
2232+ asection *sym_sec;
2233+
2234+ isym = isymbuf + ELF64_R_SYM (irel->r_info);
2235+ if (isym->st_shndx == SHN_UNDEF)
2236+ sym_sec = bfd_und_section_ptr;
2237+ else if (isym->st_shndx == SHN_ABS)
2238+ sym_sec = bfd_abs_section_ptr;
2239+ else if (isym->st_shndx == SHN_COMMON)
2240+ sym_sec = bfd_com_section_ptr;
2241+ else
2242+ sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx);
2243+
2244+ symval = _bfd_elf_rela_local_sym (abfd, isym, &sym_sec, irel);
2245+ }
2246+ else
2247+ {
2248+ unsigned long indx;
2249+ struct elf_link_hash_entry *h;
2250+
2251+ indx = ELF64_R_SYM (irel->r_info) - symtab_hdr->sh_info;
2252+ h = elf_sym_hashes (abfd)[indx];
2253+ BFD_ASSERT (h != NULL);
2254+
2255+ if (h->root.type != bfd_link_hash_defined
2256+ && h->root.type != bfd_link_hash_defweak)
2257+ /* This appears to be a reference to an undefined
2258+ symbol. Just ignore it--it will be caught by the
2259+ regular reloc processing. */
2260+ continue;
2261+
2262+ symval = (h->root.u.def.value
2263+ + h->root.u.def.section->output_section->vma
2264+ + h->root.u.def.section->output_offset);
2265+ }
2266+
2267+ /* If this is a PC-relative reloc, subtract the instr offset from
2268+ the symbol value. */
2269+ if (ELF64_R_TYPE (irel->r_info) == (int) R_MICROBLAZE_64_PCREL)
2270+ {
2271+ symval = symval + irel->r_addend
2272+ - (irel->r_offset
2273+ + sec->output_section->vma
2274+ + sec->output_offset);
2275+ }
2276+ else if (ELF64_R_TYPE (irel->r_info) == (int) R_MICROBLAZE_TEXTREL_64)
2277+ {
2278+ symval = symval + irel->r_addend - (sec->output_section->vma);
2279+ }
2280+ else
2281+ symval += irel->r_addend;
2282+
2283+ if ((symval & 0xffff8000) == 0
2284+ || (symval & 0xffff8000) == 0xffff8000)
2285+ {
2286+ /* We can delete this instruction. */
2287+ sdata->relax[sdata->relax_count].addr = irel->r_offset;
2288+ sdata->relax[sdata->relax_count].size = INST_WORD_SIZE;
2289+ sdata->relax_count++;
2290+
2291+ /* Rewrite relocation type. */
2292+ switch ((enum elf_microblaze_reloc_type) ELF64_R_TYPE (irel->r_info))
2293+ {
2294+ case R_MICROBLAZE_64_PCREL:
2295+ irel->r_info = ELF64_R_INFO (ELF64_R_SYM (irel->r_info),
2296+ (int) R_MICROBLAZE_32_PCREL_LO);
2297+ break;
2298+ case R_MICROBLAZE_64:
2299+ irel->r_info = ELF64_R_INFO (ELF64_R_SYM (irel->r_info),
2300+ (int) R_MICROBLAZE_32_LO);
2301+ break;
2302+ case R_MICROBLAZE_TEXTREL_64:
2303+ irel->r_info = ELF64_R_INFO (ELF64_R_SYM (irel->r_info),
2304+ (int) R_MICROBLAZE_TEXTREL_32_LO);
2305+ break;
2306+ default:
2307+ /* Cannot happen. */
2308+ BFD_ASSERT (false);
2309+ }
2310+ }
2311+ } /* Loop through all relocations. */
2312+
2313+ /* Loop through the relocs again, and see if anything needs to change. */
2314+ if (sdata->relax_count > 0)
2315+ {
2316+ shndx = _bfd_elf_section_from_bfd_section (abfd, sec);
2317+ rel_count = 0;
2318+ sdata->relax[sdata->relax_count].addr = sec->size;
2319+
2320+ for (irel = internal_relocs; irel < irelend; irel++, rel_count++)
2321+ {
2322+ bfd_vma nraddr;
2323+
2324+ /* Get the new reloc address. */
2325+ nraddr = irel->r_offset - calc_fixup (irel->r_offset, 0, sec);
2326+ switch ((enum elf_microblaze_reloc_type) ELF64_R_TYPE (irel->r_info))
2327+ {
2328+ default:
2329+ break;
2330+ case R_MICROBLAZE_64_PCREL:
2331+ break;
2332+ case R_MICROBLAZE_64:
2333+ case R_MICROBLAZE_32_LO:
2334+ /* If this reloc is against a symbol defined in this
2335+ section, we must check the addend to see it will put the value in
2336+ range to be adjusted, and hence must be changed. */
2337+ if (ELF64_R_SYM (irel->r_info) < symtab_hdr->sh_info)
2338+ {
2339+ isym = isymbuf + ELF64_R_SYM (irel->r_info);
2340+ /* Only handle relocs against .text. */
2341+ if (isym->st_shndx == shndx
2342+ && ELF64_ST_TYPE (isym->st_info) == STT_SECTION)
2343+ irel->r_addend -= calc_fixup (irel->r_addend, 0, sec);
2344+ }
2345+ break;
2346+ case R_MICROBLAZE_IMML_64:
2347+ {
2348+ /* This was a PC-relative instruction that was
2349+ completely resolved. */
2350+ int sfix, efix;
2351+ unsigned int val;
2352+ bfd_vma target_address;
2353+ target_address = irel->r_addend + irel->r_offset;
2354+ sfix = calc_fixup (irel->r_offset, 0, sec);
2355+ efix = calc_fixup (target_address, 0, sec);
2356+
2357+ /* Validate the in-band val. */
2358+ val = bfd_get_32 (abfd, contents + irel->r_offset);
2359+ if (val != irel->r_addend && ELF64_R_TYPE (irel->r_info) == R_MICROBLAZE_32_NONE) {
2360+ fprintf(stderr, "%d: CORRUPT relax reloc %x %lx\n", __LINE__, val, irel->r_addend);
2361+ }
2362+ irel->r_addend -= (efix - sfix);
2363+ /* Should use HOWTO. */
2364+ microblaze_bfd_write_imm_value_64 (abfd, contents + irel->r_offset,
2365+ irel->r_addend);
2366+ }
2367+ break;
2368+ case R_MICROBLAZE_NONE:
2369+ case R_MICROBLAZE_32_NONE:
2370+ {
2371+ /* This was a PC-relative instruction that was
2372+ completely resolved. */
2373+ size_t sfix, efix;
2374+ unsigned int val;
2375+ bfd_vma target_address;
2376+ target_address = irel->r_addend + irel->r_offset;
2377+ sfix = calc_fixup (irel->r_offset, 0, sec);
2378+ efix = calc_fixup (target_address, 0, sec);
2379+
2380+ /* Validate the in-band val. */
2381+ val = bfd_get_32 (abfd, contents + irel->r_offset);
2382+ if (val != irel->r_addend && ELF64_R_TYPE (irel->r_info) == R_MICROBLAZE_32_NONE) {
2383+ fprintf(stderr, "%d: CORRUPT relax reloc %x %lx\n", __LINE__, val, irel->r_addend);
2384+ }
2385+ irel->r_addend -= (efix - sfix);
2386+ /* Should use HOWTO. */
2387+ microblaze_bfd_write_imm_value_32 (abfd, contents + irel->r_offset,
2388+ irel->r_addend);
2389+ }
2390+ break;
2391+ case R_MICROBLAZE_64_NONE:
2392+ {
2393+ /* This was a PC-relative 64-bit instruction that was
2394+ completely resolved. */
2395+ size_t sfix, efix;
2396+ bfd_vma target_address;
2397+ target_address = irel->r_addend + irel->r_offset + INST_WORD_SIZE;
2398+ sfix = calc_fixup (irel->r_offset + INST_WORD_SIZE, 0, sec);
2399+ efix = calc_fixup (target_address, 0, sec);
2400+ irel->r_addend -= (efix - sfix);
2401+ microblaze_bfd_write_imm_value_32 (abfd, contents + irel->r_offset
2402+ + INST_WORD_SIZE, irel->r_addend);
2403+ }
2404+ break;
2405+ }
2406+ irel->r_offset = nraddr;
2407+ } /* Change all relocs in this section. */
2408+
2409+ /* Look through all other sections. */
2410+ for (o = abfd->sections; o != NULL; o = o->next)
2411+ {
2412+ Elf_Internal_Rela *irelocs;
2413+ Elf_Internal_Rela *irelscan, *irelscanend;
2414+ bfd_byte *ocontents;
2415+
2416+ if (o == sec
2417+ || (o->flags & SEC_RELOC) == 0
2418+ || o->reloc_count == 0)
2419+ continue;
2420+
2421+ /* We always cache the relocs. Perhaps, if info->keep_memory is
2422+ false, we should free them, if we are permitted to. */
2423+
2424+ irelocs = _bfd_elf_link_read_relocs (abfd, o, NULL, NULL, true);
2425+ if (irelocs == NULL)
2426+ goto error_return;
2427+
2428+ ocontents = NULL;
2429+ irelscanend = irelocs + o->reloc_count;
2430+ for (irelscan = irelocs; irelscan < irelscanend; irelscan++)
2431+ {
2432+ if (1 && ELF64_R_TYPE (irelscan->r_info) == (int) R_MICROBLAZE_32_NONE)
2433+ {
2434+ unsigned int val;
2435+
2436+ isym = isymbuf + ELF64_R_SYM (irelscan->r_info);
2437+
2438+ /* hax: We only do the following fixup for debug location lists. */
2439+ if (strcmp(".debug_loc", o->name))
2440+ continue;
2441+
2442+ /* This was a PC-relative instruction that was completely resolved. */
2443+ if (ocontents == NULL)
2444+ {
2445+ if (elf_section_data (o)->this_hdr.contents != NULL)
2446+ ocontents = elf_section_data (o)->this_hdr.contents;
2447+ else
2448+ {
2449+ /* We always cache the section contents.
2450+ Perhaps, if info->keep_memory is false, we
2451+ should free them, if we are permitted to. */
2452+
2453+ if (o->rawsize == 0)
2454+ o->rawsize = o->size;
2455+ ocontents = (bfd_byte *) bfd_malloc (o->rawsize);
2456+ if (ocontents == NULL)
2457+ goto error_return;
2458+ if (!bfd_get_section_contents (abfd, o, ocontents,
2459+ (file_ptr) 0,
2460+ o->rawsize))
2461+ goto error_return;
2462+ elf_section_data (o)->this_hdr.contents = ocontents;
2463+ }
2464+ }
2465+
2466+ val = bfd_get_32 (abfd, ocontents + irelscan->r_offset);
2467+ if (val != irelscan->r_addend) {
2468+ fprintf(stderr, "%d: CORRUPT relax reloc! %x %lx\n", __LINE__, val, irelscan->r_addend);
2469+ }
2470+ irelscan->r_addend -= calc_fixup (irelscan->r_addend, 0, sec);
2471+ microblaze_bfd_write_imm_value_32 (abfd, ocontents + irelscan->r_offset,
2472+ irelscan->r_addend);
2473+ }
2474+ if (ELF64_R_TYPE (irelscan->r_info) == (int) R_MICROBLAZE_32)
2475+ {
2476+ isym = isymbuf + ELF64_R_SYM (irelscan->r_info);
2477+
2478+ /* Look at the reloc only if the value has been resolved. */
2479+ if (isym->st_shndx == shndx
2480+ && (ELF64_ST_TYPE (isym->st_info) == STT_SECTION))
2481+ {
2482+ if (ocontents == NULL)
2483+ {
2484+ if (elf_section_data (o)->this_hdr.contents != NULL)
2485+ ocontents = elf_section_data (o)->this_hdr.contents;
2486+ else
2487+ {
2488+ /* We always cache the section contents.
2489+ Perhaps, if info->keep_memory is false, we
2490+ should free them, if we are permitted to. */
2491+ if (o->rawsize == 0)
2492+ o->rawsize = o->size;
2493+ ocontents = (bfd_byte *) bfd_malloc (o->rawsize);
2494+ if (ocontents == NULL)
2495+ goto error_return;
2496+ if (!bfd_get_section_contents (abfd, o, ocontents,
2497+ (file_ptr) 0,
2498+ o->rawsize))
2499+ goto error_return;
2500+ elf_section_data (o)->this_hdr.contents = ocontents;
2501+ }
2502+
2503+ }
2504+ irelscan->r_addend -= calc_fixup (irelscan->r_addend, 0, sec);
2505+ }
2506+ else if (ELF64_R_TYPE (irelscan->r_info) == (int) R_MICROBLAZE_32_SYM_OP_SYM)
2507+ {
2508+ isym = isymbuf + ELF64_R_SYM (irelscan->r_info);
2509+
2510+ /* Look at the reloc only if the value has been resolved. */
2511+ if (ocontents == NULL)
2512+ {
2513+ if (elf_section_data (o)->this_hdr.contents != NULL)
2514+ ocontents = elf_section_data (o)->this_hdr.contents;
2515+ else
2516+ {
2517+ /* We always cache the section contents.
2518+ Perhaps, if info->keep_memory is false, we
2519+ should free them, if we are permitted to. */
2520+
2521+ if (o->rawsize == 0)
2522+ o->rawsize = o->size;
2523+ ocontents = (bfd_byte *) bfd_malloc (o->rawsize);
2524+ if (ocontents == NULL)
2525+ goto error_return;
2526+ if (!bfd_get_section_contents (abfd, o, ocontents,
2527+ (file_ptr) 0,
2528+ o->rawsize))
2529+ goto error_return;
2530+ elf_section_data (o)->this_hdr.contents = ocontents;
2531+ }
2532+ }
2533+ irelscan->r_addend -= calc_fixup (irelscan->r_addend
2534+ + isym->st_value,
2535+ 0,
2536+ sec);
2537+ }
2538+ }
2539+ else if ((ELF32_R_TYPE (irelscan->r_info) == (int) R_MICROBLAZE_32_PCREL_LO)
2540+ || (ELF32_R_TYPE (irelscan->r_info)
2541+ == (int) R_MICROBLAZE_32_LO)
2542+ || (ELF32_R_TYPE (irelscan->r_info)
2543+ == (int) R_MICROBLAZE_TEXTREL_32_LO))
2544+ {
2545+ isym = isymbuf + ELF64_R_SYM (irelscan->r_info);
2546+
2547+ /* Look at the reloc only if the value has been resolved. */
2548+ if (isym->st_shndx == shndx
2549+ && (ELF64_ST_TYPE (isym->st_info) == STT_SECTION))
2550+ {
2551+ bfd_vma immediate;
2552+ bfd_vma target_address;
2553+
2554+ if (ocontents == NULL)
2555+ {
2556+ if (elf_section_data (o)->this_hdr.contents != NULL)
2557+ ocontents = elf_section_data (o)->this_hdr.contents;
2558+ else
2559+ {
2560+ /* We always cache the section contents.
2561+ Perhaps, if info->keep_memory is false, we
2562+ should free them, if we are permitted to. */
2563+ if (o->rawsize == 0)
2564+ o->rawsize = o->size;
2565+ ocontents = (bfd_byte *) bfd_malloc (o->rawsize);
2566+ if (ocontents == NULL)
2567+ goto error_return;
2568+ if (!bfd_get_section_contents (abfd, o, ocontents,
2569+ (file_ptr) 0,
2570+ o->rawsize))
2571+ goto error_return;
2572+ elf_section_data (o)->this_hdr.contents = ocontents;
2573+ }
2574+ }
2575+
2576+ unsigned long instr = bfd_get_32 (abfd, ocontents + irelscan->r_offset);
2577+ immediate = instr & 0x0000ffff;
2578+ target_address = immediate;
2579+ offset = calc_fixup (target_address, 0, sec);
2580+ immediate -= offset;
2581+ irelscan->r_addend -= offset;
2582+ microblaze_bfd_write_imm_value_32 (abfd, ocontents + irelscan->r_offset,
2583+ irelscan->r_addend);
2584+ }
2585+ }
2586+
2587+ if (ELF64_R_TYPE (irelscan->r_info) == (int) R_MICROBLAZE_64
2588+ || (ELF64_R_TYPE (irelscan->r_info) == (int) R_MICROBLAZE_TEXTREL_64))
2589+ {
2590+ isym = isymbuf + ELF64_R_SYM (irelscan->r_info);
2591+
2592+ /* Look at the reloc only if the value has been resolved. */
2593+ if (isym->st_shndx == shndx
2594+ && (ELF64_ST_TYPE (isym->st_info) == STT_SECTION))
2595+ {
2596+ if (ocontents == NULL)
2597+ {
2598+ if (elf_section_data (o)->this_hdr.contents != NULL)
2599+ ocontents = elf_section_data (o)->this_hdr.contents;
2600+ else
2601+ {
2602+ /* We always cache the section contents.
2603+ Perhaps, if info->keep_memory is false, we
2604+ should free them, if we are permitted to. */
2605+
2606+ if (o->rawsize == 0)
2607+ o->rawsize = o->size;
2608+ ocontents = (bfd_byte *) bfd_malloc (o->rawsize);
2609+ if (ocontents == NULL)
2610+ goto error_return;
2611+ if (!bfd_get_section_contents (abfd, o, ocontents,
2612+ (file_ptr) 0,
2613+ o->rawsize))
2614+ goto error_return;
2615+ elf_section_data (o)->this_hdr.contents = ocontents;
2616+ }
2617+ }
2618+ offset = calc_fixup (irelscan->r_addend, 0, sec);
2619+ irelscan->r_addend -= offset;
2620+ }
2621+ }
2622+ else if (ELF64_R_TYPE (irelscan->r_info) == (int) R_MICROBLAZE_64_PCREL)
2623+ {
2624+ isym = isymbuf + ELF64_R_SYM (irelscan->r_info);
2625+
2626+ /* Look at the reloc only if the value has been resolved. */
2627+ if (isym->st_shndx == shndx
2628+ && (ELF64_ST_TYPE (isym->st_info) == STT_SECTION))
2629+ {
2630+ bfd_vma immediate;
2631+ bfd_vma target_address;
2632+
2633+ if (ocontents == NULL)
2634+ {
2635+ if (elf_section_data (o)->this_hdr.contents != NULL)
2636+ ocontents = elf_section_data (o)->this_hdr.contents;
2637+ else
2638+ {
2639+ /* We always cache the section contents.
2640+ Perhaps, if info->keep_memory is false, we
2641+ should free them, if we are permitted to. */
2642+ if (o->rawsize == 0)
2643+ o->rawsize = o->size;
2644+ ocontents = (bfd_byte *) bfd_malloc (o->rawsize);
2645+ if (ocontents == NULL)
2646+ goto error_return;
2647+ if (!bfd_get_section_contents (abfd, o, ocontents,
2648+ (file_ptr) 0,
2649+ o->rawsize))
2650+ goto error_return;
2651+ elf_section_data (o)->this_hdr.contents = ocontents;
2652+ }
2653+ }
2654+ unsigned long instr_hi = bfd_get_32 (abfd, ocontents
2655+ + irelscan->r_offset);
2656+ unsigned long instr_lo = bfd_get_32 (abfd, ocontents
2657+ + irelscan->r_offset
2658+ + INST_WORD_SIZE);
2659+ immediate = (instr_hi & 0x0000ffff) << 16;
2660+ immediate |= (instr_lo & 0x0000ffff);
2661+ target_address = immediate;
2662+ offset = calc_fixup (target_address, 0, sec);
2663+ immediate -= offset;
2664+ irelscan->r_addend -= offset;
2665+ microblaze_bfd_write_imm_value_64 (abfd, ocontents
2666+ + irelscan->r_offset, immediate);
2667+ }
2668+ }
2669+ }
2670+ }
2671+
2672+ /* Adjust the local symbols defined in this section. */
2673+ isymend = isymbuf + symtab_hdr->sh_info;
2674+ for (isym = isymbuf; isym < isymend; isym++)
2675+ {
2676+ if (isym->st_shndx == shndx)
2677+ {
2678+ isym->st_value -= calc_fixup (isym->st_value, 0, sec);
2679+ if (isym->st_size)
2680+ isym->st_size -= calc_fixup (isym->st_value, isym->st_size, sec);
2681+ }
2682+ }
2683+
2684+ /* Now adjust the global symbols defined in this section. */
2685+ isym = isymbuf + symtab_hdr->sh_info;
2686+ symcount = (symtab_hdr->sh_size / sizeof (Elf64_External_Sym)) - symtab_hdr->sh_info;
2687+ for (sym_index = 0; sym_index < symcount; sym_index++)
2688+ {
2689+ sym_hash = elf_sym_hashes (abfd)[sym_index];
2690+ if ((sym_hash->root.type == bfd_link_hash_defined
2691+ || sym_hash->root.type == bfd_link_hash_defweak)
2692+ && sym_hash->root.u.def.section == sec)
2693+ {
2694+ sym_hash->root.u.def.value -= calc_fixup (sym_hash->root.u.def.value,
2695+ 0, sec);
2696+ if (sym_hash->size)
2697+ sym_hash->size -= calc_fixup (sym_hash->root.u.def.value,
2698+ sym_hash->size, sec);
2699+ }
2700+ }
2701+
2702+ /* Physically move the code and change the cooked size. */
2703+ dest = sdata->relax[0].addr;
2704+ for (i = 0; i < sdata->relax_count; i++)
2705+ {
2706+ size_t len;
2707+ src = sdata->relax[i].addr + sdata->relax[i].size;
2708+ len = (sdata->relax[i+1].addr - sdata->relax[i].addr
2709+ - sdata->relax[i].size);
2710+
2711+ memmove (contents + dest, contents + src, len);
2712+ sec->size -= sdata->relax[i].size;
2713+ dest += len;
2714+ }
2715+
2716+ elf_section_data (sec)->relocs = internal_relocs;
2717+ free_relocs = NULL;
2718+
2719+ elf_section_data (sec)->this_hdr.contents = contents;
2720+ free_contents = NULL;
2721+
2722+ symtab_hdr->contents = (bfd_byte *) isymbuf;
2723+ }
2724+
2725+ free (free_relocs);
2726+ free_relocs = NULL;
2727+
2728+ if (free_contents != NULL)
2729+ {
2730+ if (!link_info->keep_memory)
2731+ free (free_contents);
2732+ else
2733+ /* Cache the section contents for elf_link_input_bfd. */
2734+ elf_section_data (sec)->this_hdr.contents = contents;
2735+ free_contents = NULL;
2736+ }
2737+
2738+ if (sdata->relax_count == 0)
2739+ {
2740+ *again = false;
2741+ free (sdata->relax);
2742+ sdata->relax = NULL;
2743+ }
2744+ else
2745+ *again = true;
2746+ return true;
2747+
2748+ error_return:
2749+ free (free_relocs);
2750+ free (free_contents);
2751+ free (sdata->relax);
2752+ sdata->relax = NULL;
2753+ sdata->relax_count = 0;
2754+ return false;
2755+}
2756+
2757+/* Return the section that should be marked against GC for a given
2758+ relocation. */
2759+
2760+static asection *
2761+microblaze_elf_gc_mark_hook (asection *sec,
2762+ struct bfd_link_info * info,
2763+ Elf_Internal_Rela * rel,
2764+ struct elf_link_hash_entry * h,
2765+ Elf_Internal_Sym * sym)
2766+{
2767+ if (h != NULL)
2768+ switch (ELF64_R_TYPE (rel->r_info))
2769+ {
2770+ case R_MICROBLAZE_GNU_VTINHERIT:
2771+ case R_MICROBLAZE_GNU_VTENTRY:
2772+ return NULL;
2773+ }
2774+
2775+ return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym);
2776+}
2777+
2778+/* PIC support. */
2779+
2780+#define PLT_ENTRY_SIZE 16
2781+
2782+#define PLT_ENTRY_WORD_0 0xb0000000 /* "imm 0". */
2783+#define PLT_ENTRY_WORD_1 0xe9940000 /* "lwi r12,r20,0" - relocated to lwi r12,r20,func@GOT. */
2784+#define PLT_ENTRY_WORD_1_NOPIC 0xe9800000 /* "lwi r12,r0,0" - non-PIC object. */
2785+#define PLT_ENTRY_WORD_2 0x98186000 /* "brad r12". */
2786+#define PLT_ENTRY_WORD_3 0x80000000 /* "nop". */
2787+
2788+/* Create .got, .gotplt, and .rela.got sections in DYNOBJ, and set up
2789+ shortcuts to them in our hash table. */
2790+
2791+static bool
2792+update_local_sym_info (bfd *abfd,
2793+ Elf_Internal_Shdr *symtab_hdr,
2794+ unsigned long r_symndx,
2795+ unsigned int tls_type)
2796+{
2797+ bfd_signed_vma *local_got_refcounts = elf_local_got_refcounts (abfd);
2798+ unsigned char *local_got_tls_masks;
2799+
2800+ if (local_got_refcounts == NULL)
2801+ {
2802+ bfd_size_type size = symtab_hdr->sh_info;
2803+
2804+ size *= (sizeof (*local_got_refcounts) + sizeof (*local_got_tls_masks));
2805+ local_got_refcounts = bfd_zalloc (abfd, size);
2806+ if (local_got_refcounts == NULL)
2807+ return false;
2808+ elf_local_got_refcounts (abfd) = local_got_refcounts;
2809+ }
2810+
2811+ local_got_tls_masks =
2812+ (unsigned char *) (local_got_refcounts + symtab_hdr->sh_info);
2813+ local_got_tls_masks[r_symndx] |= tls_type;
2814+ local_got_refcounts[r_symndx] += 1;
2815+
2816+ return true;
2817+}
2818+/* Look through the relocs for a section during the first phase. */
2819+
2820+static bool
2821+microblaze_elf_check_relocs (bfd * abfd,
2822+ struct bfd_link_info * info,
2823+ asection * sec,
2824+ const Elf_Internal_Rela * relocs)
2825+{
2826+ Elf_Internal_Shdr * symtab_hdr;
2827+ struct elf_link_hash_entry ** sym_hashes;
2828+ struct elf_link_hash_entry ** sym_hashes_end;
2829+ const Elf_Internal_Rela * rel;
2830+ const Elf_Internal_Rela * rel_end;
2831+ struct elf64_mb_link_hash_table *htab;
2832+ asection *sreloc = NULL;
2833+
2834+ if (bfd_link_relocatable (info))
2835+ return true;
2836+
2837+ htab = elf64_mb_hash_table (info);
2838+ if (htab == NULL)
2839+ return false;
2840+
2841+ symtab_hdr = & elf_tdata (abfd)->symtab_hdr;
2842+ sym_hashes = elf_sym_hashes (abfd);
2843+ sym_hashes_end = sym_hashes + symtab_hdr->sh_size / sizeof (Elf64_External_Sym);
2844+ if (!elf_bad_symtab (abfd))
2845+ sym_hashes_end -= symtab_hdr->sh_info;
2846+
2847+ rel_end = relocs + sec->reloc_count;
2848+
2849+ for (rel = relocs; rel < rel_end; rel++)
2850+ {
2851+ unsigned int r_type;
2852+ struct elf_link_hash_entry * h;
2853+ unsigned long r_symndx;
2854+ unsigned char tls_type = 0;
2855+
2856+ r_symndx = ELF64_R_SYM (rel->r_info);
2857+ r_type = ELF64_R_TYPE (rel->r_info);
2858+
2859+ if (r_symndx < symtab_hdr->sh_info)
2860+ h = NULL;
2861+ else
2862+ {
2863+ h = sym_hashes [r_symndx - symtab_hdr->sh_info];
2864+ while (h->root.type == bfd_link_hash_indirect
2865+ || h->root.type == bfd_link_hash_warning)
2866+ h = (struct elf_link_hash_entry *) h->root.u.i.link;
2867+ }
2868+
2869+ switch (r_type)
2870+ {
2871+ /* This relocation describes the C++ object vtable hierarchy.
2872+ Reconstruct it for later use during GC. */
2873+ case R_MICROBLAZE_GNU_VTINHERIT:
2874+ if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset))
2875+ return false;
2876+ break;
2877+
2878+ /* This relocation describes which C++ vtable entries are actually
2879+ used. Record for later use during GC. */
2880+ case R_MICROBLAZE_GNU_VTENTRY:
2881+ if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_addend))
2882+ return false;
2883+ break;
2884+
2885+ /* This relocation requires .plt entry. */
2886+ case R_MICROBLAZE_PLT_64:
2887+ if (h != NULL)
2888+ {
2889+ h->needs_plt = 1;
2890+ h->plt.refcount += 1;
2891+ }
2892+ break;
2893+
2894+ /* This relocation requires .got entry. */
2895+ case R_MICROBLAZE_TLSGD:
2896+ tls_type |= (TLS_TLS | TLS_GD);
2897+ goto dogottls;
2898+ case R_MICROBLAZE_TLSLD:
2899+ tls_type |= (TLS_TLS | TLS_LD);
2900+ /* Fall through. */
2901+ dogottls:
2902+ sec->has_tls_reloc = 1;
2903+ /* Fall through. */
2904+ case R_MICROBLAZE_GOT_64:
2905+ if (htab->elf.sgot == NULL)
2906+ {
2907+ if (htab->elf.dynobj == NULL)
2908+ htab->elf.dynobj = abfd;
2909+ if (!_bfd_elf_create_got_section (htab->elf.dynobj, info))
2910+ return false;
2911+ }
2912+ if (h != NULL)
2913+ {
2914+ h->got.refcount += 1;
2915+ elf64_mb_hash_entry (h)->tls_mask |= tls_type;
2916+ }
2917+ else
2918+ {
2919+ if (! update_local_sym_info(abfd, symtab_hdr, r_symndx, tls_type) )
2920+ return false;
2921+ }
2922+ break;
2923+
2924+ case R_MICROBLAZE_GOTOFF_64:
2925+ case R_MICROBLAZE_GOTOFF_32:
2926+ if (htab->elf.sgot == NULL)
2927+ {
2928+ if (htab->elf.dynobj == NULL)
2929+ htab->elf.dynobj = abfd;
2930+ if (!_bfd_elf_create_got_section (htab->elf.dynobj, info))
2931+ return false;
2932+ }
2933+ break;
2934+
2935+ case R_MICROBLAZE_64:
2936+ case R_MICROBLAZE_64_PCREL:
2937+ case R_MICROBLAZE_32:
2938+ {
2939+ if (h != NULL && !bfd_link_pic (info))
2940+ {
2941+ /* we may need a copy reloc. */
2942+ h->non_got_ref = 1;
2943+
2944+ /* we may also need a .plt entry. */
2945+ h->plt.refcount += 1;
2946+ if (ELF64_R_TYPE (rel->r_info) != R_MICROBLAZE_64_PCREL)
2947+ h->pointer_equality_needed = 1;
2948+ }
2949+
2950+
2951+ /* If we are creating a shared library, and this is a reloc
2952+ against a global symbol, or a non PC relative reloc
2953+ against a local symbol, then we need to copy the reloc
2954+ into the shared library. However, if we are linking with
2955+ -Bsymbolic, we do not need to copy a reloc against a
2956+ global symbol which is defined in an object we are
2957+ including in the link (i.e., DEF_REGULAR is set). At
2958+ this point we have not seen all the input files, so it is
2959+ possible that DEF_REGULAR is not set now but will be set
2960+ later (it is never cleared). In case of a weak definition,
2961+ DEF_REGULAR may be cleared later by a strong definition in
2962+ a shared library. We account for that possibility below by
2963+ storing information in the relocs_copied field of the hash
2964+ table entry. A similar situation occurs when creating
2965+ shared libraries and symbol visibility changes render the
2966+ symbol local.
2967+
2968+ If on the other hand, we are creating an executable, we
2969+ may need to keep relocations for symbols satisfied by a
2970+ dynamic library if we manage to avoid copy relocs for the
2971+ symbol. */
2972+
2973+ if ((bfd_link_pic (info)
2974+ && (sec->flags & SEC_ALLOC) != 0
2975+ && (r_type != R_MICROBLAZE_64_PCREL
2976+ || (h != NULL
2977+ && (! info->symbolic
2978+ || h->root.type == bfd_link_hash_defweak
2979+ || !h->def_regular))))
2980+ || (!bfd_link_pic (info)
2981+ && (sec->flags & SEC_ALLOC) != 0
2982+ && h != NULL
2983+ && (h->root.type == bfd_link_hash_defweak
2984+ || !h->def_regular)))
2985+ {
2986+ struct elf_dyn_relocs *p;
2987+ struct elf_dyn_relocs **head;
2988+
2989+ /* When creating a shared object, we must copy these
2990+ relocs into the output file. We create a reloc
2991+ section in dynobj and make room for the reloc. */
2992+
2993+ if (sreloc == NULL)
2994+ {
2995+ bfd *dynobj;
2996+
2997+ if (htab->elf.dynobj == NULL)
2998+ htab->elf.dynobj = abfd;
2999+ dynobj = htab->elf.dynobj;
3000+
3001+ sreloc = _bfd_elf_make_dynamic_reloc_section (sec, dynobj,
3002+ 2, abfd, 1);
3003+ if (sreloc == NULL)
3004+ return false;
3005+ }
3006+
3007+ /* If this is a global symbol, we count the number of
3008+ relocations we need for this symbol. */
3009+ if (h != NULL)
3010+ head = &h->dyn_relocs;
3011+ else
3012+ {
3013+ /* Track dynamic relocs needed for local syms too.
3014+ We really need local syms available to do this
3015+ easily. Oh well. */
3016+
3017+ asection *s;
3018+ Elf_Internal_Sym *isym;
3019+ void *vpp;
3020+
3021+ isym = bfd_sym_from_r_symndx (&htab->elf.sym_cache,
3022+ abfd, r_symndx);
3023+ if (isym == NULL)
3024+ return false;
3025+
3026+ s = bfd_section_from_elf_index (abfd, isym->st_shndx);
3027+ if (s == NULL)
3028+ return false;
3029+
3030+ vpp = &elf_section_data (s)->local_dynrel;
3031+ head = (struct elf_dyn_relocs **) vpp;
3032+ }
3033+
3034+ p = *head;
3035+ if (p == NULL || p->sec != sec)
3036+ {
3037+ size_t amt = sizeof *p;
3038+ p = ((struct elf_dyn_relocs *)
3039+ bfd_alloc (htab->elf.dynobj, amt));
3040+ if (p == NULL)
3041+ return false;
3042+ p->next = *head;
3043+ *head = p;
3044+ p->sec = sec;
3045+ p->count = 0;
3046+ p->pc_count = 0;
3047+ }
3048+
3049+ p->count += 1;
3050+ if (r_type == R_MICROBLAZE_64_PCREL)
3051+ p->pc_count += 1;
3052+ }
3053+ }
3054+ break;
3055+ }
3056+ }
3057+
3058+ return true;
3059+}
3060+
3061+/* Copy the extra info we tack onto an elf_link_hash_entry. */
3062+
3063+static void
3064+microblaze_elf_copy_indirect_symbol (struct bfd_link_info *info,
3065+ struct elf_link_hash_entry *dir,
3066+ struct elf_link_hash_entry *ind)
3067+{
3068+ struct elf64_mb_link_hash_entry *edir, *eind;
3069+
3070+ edir = (struct elf64_mb_link_hash_entry *) dir;
3071+ eind = (struct elf64_mb_link_hash_entry *) ind;
3072+
3073+ edir->tls_mask |= eind->tls_mask;
3074+
3075+ _bfd_elf_link_hash_copy_indirect (info, dir, ind);
3076+}
3077+
3078+static bool
3079+microblaze_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
3080+ struct elf_link_hash_entry *h)
3081+{
3082+ struct elf64_mb_link_hash_table *htab;
3083+ asection *s, *srel;
3084+ unsigned int power_of_two;
3085+
3086+ htab = elf64_mb_hash_table (info);
3087+ if (htab == NULL)
3088+ return false;
3089+
3090+ /* If this is a function, put it in the procedure linkage table. We
3091+ will fill in the contents of the procedure linkage table later,
3092+ when we know the address of the .got section. */
3093+ if (h->type == STT_FUNC
3094+ || h->needs_plt)
3095+ {
3096+ if (h->plt.refcount <= 0
3097+ || SYMBOL_CALLS_LOCAL (info, h)
3098+ || (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT
3099+ && h->root.type == bfd_link_hash_undefweak))
3100+ {
3101+ /* This case can occur if we saw a PLT reloc in an input
3102+ file, but the symbol was never referred to by a dynamic
3103+ object, or if all references were garbage collected. In
3104+ such a case, we don't actually need to build a procedure
3105+ linkage table, and we can just do a PC32 reloc instead. */
3106+ h->plt.offset = (bfd_vma) -1;
3107+ h->needs_plt = 0;
3108+ }
3109+
3110+ return true;
3111+ }
3112+ else
3113+ /* It's possible that we incorrectly decided a .plt reloc was
3114+ needed for an R_MICROBLAZE_64_PCREL reloc to a non-function sym in
3115+ check_relocs. We can't decide accurately between function and
3116+ non-function syms in check-relocs; Objects loaded later in
3117+ the link may change h->type. So fix it now. */
3118+ h->plt.offset = (bfd_vma) -1;
3119+
3120+ /* If this is a weak symbol, and there is a real definition, the
3121+ processor independent code will have arranged for us to see the
3122+ real definition first, and we can just use the same value. */
3123+ if (h->is_weakalias)
3124+ {
3125+ struct elf_link_hash_entry *def = weakdef (h);
3126+ BFD_ASSERT (def->root.type == bfd_link_hash_defined);
3127+ h->root.u.def.section = def->root.u.def.section;
3128+ h->root.u.def.value = def->root.u.def.value;
3129+ return true;
3130+ }
3131+
3132+ /* This is a reference to a symbol defined by a dynamic object which
3133+ is not a function. */
3134+
3135+ /* If we are creating a shared library, we must presume that the
3136+ only references to the symbol are via the global offset table.
3137+ For such cases we need not do anything here; the relocations will
3138+ be handled correctly by relocate_section. */
3139+ if (bfd_link_pic (info))
3140+ return true;
3141+
3142+ /* If there are no references to this symbol that do not use the
3143+ GOT, we don't need to generate a copy reloc. */
3144+ if (!h->non_got_ref)
3145+ return true;
3146+
3147+ /* If -z nocopyreloc was given, we won't generate them either. */
3148+ if (info->nocopyreloc)
3149+ {
3150+ h->non_got_ref = 0;
3151+ return true;
3152+ }
3153+
3154+ /* If we don't find any dynamic relocs in read-only sections, then
3155+ we'll be keeping the dynamic relocs and avoiding the copy reloc. */
3156+ if (!_bfd_elf_readonly_dynrelocs (h))
3157+ {
3158+ h->non_got_ref = 0;
3159+ return true;
3160+ }
3161+
3162+ /* We must allocate the symbol in our .dynbss section, which will
3163+ become part of the .bss section of the executable. There will be
3164+ an entry for this symbol in the .dynsym section. The dynamic
3165+ object will contain position independent code, so all references
3166+ from the dynamic object to this symbol will go through the global
3167+ offset table. The dynamic linker will use the .dynsym entry to
3168+ determine the address it must put in the global offset table, so
3169+ both the dynamic object and the regular object will refer to the
3170+ same memory location for the variable. */
3171+
3172+ /* We must generate a R_MICROBLAZE_COPY reloc to tell the dynamic linker
3173+ to copy the initial value out of the dynamic object and into the
3174+ runtime process image. */
3175+ if ((h->root.u.def.section->flags & SEC_READONLY) != 0)
3176+ {
3177+ s = htab->elf.sdynrelro;
3178+ srel = htab->elf.sreldynrelro;
3179+ }
3180+ else
3181+ {
3182+ s = htab->elf.sdynbss;
3183+ srel = htab->elf.srelbss;
3184+ }
3185+ if ((h->root.u.def.section->flags & SEC_ALLOC) != 0)
3186+ {
3187+ srel->size += sizeof (Elf64_External_Rela);
3188+ h->needs_copy = 1;
3189+ }
3190+
3191+ /* We need to figure out the alignment required for this symbol. I
3192+ have no idea how ELF linkers handle this. */
3193+ power_of_two = bfd_log2 (h->size);
3194+ if (power_of_two > 3)
3195+ power_of_two = 3;
3196+
3197+ /* Apply the required alignment. */
3198+ s->size = BFD_ALIGN (s->size, (bfd_size_type) (1 << power_of_two));
3199+ if (power_of_two > s->alignment_power)
3200+ {
3201+ if (!bfd_set_section_alignment (s, power_of_two))
3202+ return false;
3203+ }
3204+
3205+ /* Define the symbol as being at this point in the section. */
3206+ h->root.u.def.section = s;
3207+ h->root.u.def.value = s->size;
3208+
3209+ /* Increment the section size to make room for the symbol. */
3210+ s->size += h->size;
3211+ return true;
3212+}
3213+
3214+/* Allocate space in .plt, .got and associated reloc sections for
3215+ dynamic relocs. */
3216+
3217+static bool
3218+allocate_dynrelocs (struct elf_link_hash_entry *h, void * dat)
3219+{
3220+ struct bfd_link_info *info;
3221+ struct elf64_mb_link_hash_table *htab;
3222+ struct elf64_mb_link_hash_entry *eh;
3223+ struct elf_dyn_relocs *p;
3224+
3225+ if (h->root.type == bfd_link_hash_indirect)
3226+ return true;
3227+
3228+ info = (struct bfd_link_info *) dat;
3229+ htab = elf64_mb_hash_table (info);
3230+ if (htab == NULL)
3231+ return false;
3232+
3233+ if (htab->elf.dynamic_sections_created
3234+ && h->plt.refcount > 0)
3235+ {
3236+ /* Make sure this symbol is output as a dynamic symbol.
3237+ Undefined weak syms won't yet be marked as dynamic. */
3238+ if (h->dynindx == -1
3239+ && !h->forced_local)
3240+ {
3241+ if (! bfd_elf_link_record_dynamic_symbol (info, h))
3242+ return false;
3243+ }
3244+
3245+ if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, bfd_link_pic (info), h))
3246+ {
3247+ asection *s = htab->elf.splt;
3248+
3249+ /* The first entry in .plt is reserved. */
3250+ if (s->size == 0)
3251+ s->size = PLT_ENTRY_SIZE;
3252+
3253+ h->plt.offset = s->size;
3254+
3255+ /* If this symbol is not defined in a regular file, and we are
3256+ not generating a shared library, then set the symbol to this
3257+ location in the .plt. This is required to make function
3258+ pointers compare as equal between the normal executable and
3259+ the shared library. */
3260+ if (! bfd_link_pic (info)
3261+ && !h->def_regular)
3262+ {
3263+ h->root.u.def.section = s;
3264+ h->root.u.def.value = h->plt.offset;
3265+ }
3266+
3267+ /* Make room for this entry. */
3268+ s->size += PLT_ENTRY_SIZE;
3269+
3270+ /* We also need to make an entry in the .got.plt section, which
3271+ will be placed in the .got section by the linker script. */
3272+ htab->elf.sgotplt->size += 4;
3273+
3274+ /* We also need to make an entry in the .rel.plt section. */
3275+ htab->elf.srelplt->size += sizeof (Elf32_External_Rela);
3276+ }
3277+ else
3278+ {
3279+ h->plt.offset = (bfd_vma) -1;
3280+ h->needs_plt = 0;
3281+ }
3282+ }
3283+ else
3284+ {
3285+ h->plt.offset = (bfd_vma) -1;
3286+ h->needs_plt = 0;
3287+ }
3288+
3289+ eh = (struct elf64_mb_link_hash_entry *) h;
3290+ if (h->got.refcount > 0)
3291+ {
3292+ unsigned int need;
3293+ asection *s;
3294+
3295+ /* Make sure this symbol is output as a dynamic symbol.
3296+ Undefined weak syms won't yet be marked as dynamic. */
3297+ if (h->dynindx == -1
3298+ && !h->forced_local)
3299+ {
3300+ if (! bfd_elf_link_record_dynamic_symbol (info, h))
3301+ return false;
3302+ }
3303+
3304+ need = 0;
3305+ if ((eh->tls_mask & TLS_TLS) != 0)
3306+ {
3307+ /* Handle TLS Symbol */
3308+ if ((eh->tls_mask & TLS_LD) != 0)
3309+ {
3310+ if (!eh->elf.def_dynamic)
3311+ /* We'll just use htab->tlsld_got.offset. This should
3312+ always be the case. It's a little odd if we have
3313+ a local dynamic reloc against a non-local symbol. */
3314+ htab->tlsld_got.refcount += 1;
3315+ else
3316+ need += 8;
3317+ }
3318+ if ((eh->tls_mask & TLS_GD) != 0)
3319+ need += 8;
3320+ }
3321+ else
3322+ {
3323+ /* Regular (non-TLS) symbol */
3324+ need += 4;
3325+ }
3326+ if (need == 0)
3327+ {
3328+ h->got.offset = (bfd_vma) -1;
3329+ }
3330+ else
3331+ {
3332+ s = htab->elf.sgot;
3333+ h->got.offset = s->size;
3334+ s->size += need;
3335+ htab->elf.srelgot->size += need * (sizeof (Elf64_External_Rela) / 4);
3336+ }
3337+ }
3338+ else
3339+ h->got.offset = (bfd_vma) -1;
3340+
3341+ if (h->dyn_relocs == NULL)
3342+ return true;
3343+
3344+ /* In the shared -Bsymbolic case, discard space allocated for
3345+ dynamic pc-relative relocs against symbols which turn out to be
3346+ defined in regular objects. For the normal shared case, discard
3347+ space for pc-relative relocs that have become local due to symbol
3348+ visibility changes. */
3349+
3350+ if (bfd_link_pic (info))
3351+ {
3352+ if (h->def_regular
3353+ && (h->forced_local
3354+ || info->symbolic))
3355+ {
3356+ struct elf_dyn_relocs **pp;
3357+
3358+ for (pp = &h->dyn_relocs; (p = *pp) != NULL; )
3359+ {
3360+ p->count -= p->pc_count;
3361+ p->pc_count = 0;
3362+ if (p->count == 0)
3363+ *pp = p->next;
3364+ else
3365+ pp = &p->next;
3366+ }
3367+ }
3368+ else if (UNDEFWEAK_NO_DYNAMIC_RELOC (info, h))
3369+ h->dyn_relocs = NULL;
3370+ }
3371+ else
3372+ {
3373+ /* For the non-shared case, discard space for relocs against
3374+ symbols which turn out to need copy relocs or are not
3375+ dynamic. */
3376+
3377+ if (!h->non_got_ref
3378+ && ((h->def_dynamic
3379+ && !h->def_regular)
3380+ || (htab->elf.dynamic_sections_created
3381+ && (h->root.type == bfd_link_hash_undefweak
3382+ || h->root.type == bfd_link_hash_undefined))))
3383+ {
3384+ /* Make sure this symbol is output as a dynamic symbol.
3385+ Undefined weak syms won't yet be marked as dynamic. */
3386+ if (h->dynindx == -1
3387+ && !h->forced_local)
3388+ {
3389+ if (! bfd_elf_link_record_dynamic_symbol (info, h))
3390+ return false;
3391+ }
3392+
3393+ /* If that succeeded, we know we'll be keeping all the
3394+ relocs. */
3395+ if (h->dynindx != -1)
3396+ goto keep;
3397+ }
3398+
3399+ h->dyn_relocs = NULL;
3400+
3401+ keep: ;
3402+ }
3403+
3404+ /* Finally, allocate space. */
3405+ for (p = h->dyn_relocs; p != NULL; p = p->next)
3406+ {
3407+ asection *sreloc = elf_section_data (p->sec)->sreloc;
3408+ sreloc->size += p->count * sizeof (Elf64_External_Rela);
3409+ }
3410+
3411+ return true;
3412+}
3413+
3414+/* Set the sizes of the dynamic sections. */
3415+
3416+static bool
3417+microblaze_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
3418+ struct bfd_link_info *info)
3419+{
3420+ struct elf64_mb_link_hash_table *htab;
3421+ bfd *dynobj;
3422+ asection *s;
3423+ bfd *ibfd;
3424+
3425+ htab = elf64_mb_hash_table (info);
3426+ if (htab == NULL)
3427+ return false;
3428+
3429+ dynobj = htab->elf.dynobj;
3430+ BFD_ASSERT (dynobj != NULL);
3431+
3432+ /* Set up .got offsets for local syms, and space for local dynamic
3433+ relocs. */
3434+ for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link.next)
3435+ {
3436+ bfd_signed_vma *local_got;
3437+ bfd_signed_vma *end_local_got;
3438+ bfd_size_type locsymcount;
3439+ Elf_Internal_Shdr *symtab_hdr;
3440+ unsigned char *lgot_masks;
3441+ asection *srel;
3442+
3443+ if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour)
3444+ continue;
3445+
3446+ for (s = ibfd->sections; s != NULL; s = s->next)
3447+ {
3448+ struct elf_dyn_relocs *p;
3449+
3450+ for (p = ((struct elf_dyn_relocs *)
3451+ elf_section_data (s)->local_dynrel);
3452+ p != NULL;
3453+ p = p->next)
3454+ {
3455+ if (!bfd_is_abs_section (p->sec)
3456+ && bfd_is_abs_section (p->sec->output_section))
3457+ {
3458+ /* Input section has been discarded, either because
3459+ it is a copy of a linkonce section or due to
3460+ linker script /DISCARD/, so we'll be discarding
3461+ the relocs too. */
3462+ }
3463+ else if (p->count != 0)
3464+ {
3465+ srel = elf_section_data (p->sec)->sreloc;
3466+ srel->size += p->count * sizeof (Elf64_External_Rela);
3467+ if ((p->sec->output_section->flags & SEC_READONLY) != 0)
3468+ info->flags |= DF_TEXTREL;
3469+ }
3470+ }
3471+ }
3472+
3473+ local_got = elf_local_got_refcounts (ibfd);
3474+ if (!local_got)
3475+ continue;
3476+
3477+ symtab_hdr = &elf_tdata (ibfd)->symtab_hdr;
3478+ locsymcount = symtab_hdr->sh_info;
3479+ end_local_got = local_got + locsymcount;
3480+ lgot_masks = (unsigned char *) end_local_got;
3481+ s = htab->elf.sgot;
3482+ srel = htab->elf.srelgot;
3483+
3484+ for (; local_got < end_local_got; ++local_got, ++lgot_masks)
3485+ {
3486+ if (*local_got > 0)
3487+ {
3488+ unsigned int need = 0;
3489+ if ((*lgot_masks & TLS_TLS) != 0)
3490+ {
3491+ if ((*lgot_masks & TLS_GD) != 0)
3492+ need += 8;
3493+ if ((*lgot_masks & TLS_LD) != 0)
3494+ htab->tlsld_got.refcount += 1;
3495+ }
3496+ else
3497+ need += 4;
3498+
3499+ if (need == 0)
3500+ {
3501+ *local_got = (bfd_vma) -1;
3502+ }
3503+ else
3504+ {
3505+ *local_got = s->size;
3506+ s->size += need;
3507+ if (bfd_link_pic (info))
3508+ srel->size += need * (sizeof (Elf64_External_Rela) / 4);
3509+ }
3510+ }
3511+ else
3512+ *local_got = (bfd_vma) -1;
3513+ }
3514+ }
3515+
3516+ /* Allocate global sym .plt and .got entries, and space for global
3517+ sym dynamic relocs. */
3518+ elf_link_hash_traverse (elf_hash_table (info), allocate_dynrelocs, info);
3519+
3520+ if (htab->tlsld_got.refcount > 0)
3521+ {
3522+ htab->tlsld_got.offset = htab->elf.sgot->size;
3523+ htab->elf.sgot->size += 8;
3524+ if (bfd_link_pic (info))
3525+ htab->elf.srelgot->size += sizeof (Elf64_External_Rela);
3526+ }
3527+ else
3528+ htab->tlsld_got.offset = (bfd_vma) -1;
3529+
3530+ if (elf_hash_table (info)->dynamic_sections_created)
3531+ {
3532+ /* Make space for the trailing nop in .plt. */
3533+ if (htab->elf.splt->size > 0)
3534+ htab->elf.splt->size += 4;
3535+ }
3536+
3537+ /* The check_relocs and adjust_dynamic_symbol entry points have
3538+ determined the sizes of the various dynamic sections. Allocate
3539+ memory for them. */
3540+ for (s = dynobj->sections; s != NULL; s = s->next)
3541+ {
3542+ const char *name;
3543+ bool strip = false;
3544+
3545+ if ((s->flags & SEC_LINKER_CREATED) == 0)
3546+ continue;
3547+
3548+ /* It's OK to base decisions on the section name, because none
3549+ of the dynobj section names depend upon the input files. */
3550+ name = bfd_section_name (s);
3551+
3552+ if (startswith (name, ".rela"))
3553+ {
3554+ if (s->size == 0)
3555+ {
3556+ /* If we don't need this section, strip it from the
3557+ output file. This is to handle .rela.bss and
3558+ .rela.plt. We must create it in
3559+ create_dynamic_sections, because it must be created
3560+ before the linker maps input sections to output
3561+ sections. The linker does that before
3562+ adjust_dynamic_symbol is called, and it is that
3563+ function which decides whether anything needs to go
3564+ into these sections. */
3565+ strip = true;
3566+ }
3567+ else
3568+ {
3569+ /* We use the reloc_count field as a counter if we need
3570+ to copy relocs into the output file. */
3571+ s->reloc_count = 0;
3572+ }
3573+ }
3574+ else if (s != htab->elf.splt
3575+ && s != htab->elf.sgot
3576+ && s != htab->elf.sgotplt
3577+ && s != htab->elf.sdynbss
3578+ && s != htab->elf.sdynrelro)
3579+ {
3580+ /* It's not one of our sections, so don't allocate space. */
3581+ continue;
3582+ }
3583+
3584+ if (strip)
3585+ {
3586+ s->flags |= SEC_EXCLUDE;
3587+ continue;
3588+ }
3589+
3590+ /* Allocate memory for the section contents. */
3591+ /* FIXME: This should be a call to bfd_alloc not bfd_zalloc.
3592+ Unused entries should be reclaimed before the section's contents
3593+ are written out, but at the moment this does not happen. Thus in
3594+ order to prevent writing out garbage, we initialise the section's
3595+ contents to zero. */
3596+ s->contents = (bfd_byte *) bfd_zalloc (dynobj, s->size);
3597+ if (s->contents == NULL && s->size != 0)
3598+ return false;
3599+ }
3600+
3601+ /* ??? Force DF_BIND_NOW? */
3602+ info->flags |= DF_BIND_NOW;
3603+ return _bfd_elf_add_dynamic_tags (output_bfd, info, true);
3604+}
3605+
3606+/* Finish up dynamic symbol handling. We set the contents of various
3607+ dynamic sections here. */
3608+
3609+static bool
3610+microblaze_elf_finish_dynamic_symbol (bfd *output_bfd,
3611+ struct bfd_link_info *info,
3612+ struct elf_link_hash_entry *h,
3613+ Elf_Internal_Sym *sym)
3614+{
3615+ struct elf64_mb_link_hash_table *htab;
3616+ struct elf64_mb_link_hash_entry *eh = elf64_mb_hash_entry(h);
3617+
3618+ htab = elf64_mb_hash_table (info);
3619+ if (htab == NULL)
3620+ return false;
3621+
3622+ if (h->plt.offset != (bfd_vma) -1)
3623+ {
3624+ asection *splt;
3625+ asection *srela;
3626+ asection *sgotplt;
3627+ Elf_Internal_Rela rela;
3628+ bfd_byte *loc;
3629+ bfd_vma plt_index;
3630+ bfd_vma got_offset;
3631+ bfd_vma got_addr;
3632+
3633+ /* This symbol has an entry in the procedure linkage table. Set
3634+ it up. */
3635+ BFD_ASSERT (h->dynindx != -1);
3636+
3637+ splt = htab->elf.splt;
3638+ srela = htab->elf.srelplt;
3639+ sgotplt = htab->elf.sgotplt;
3640+ BFD_ASSERT (splt != NULL && srela != NULL && sgotplt != NULL);
3641+
3642+ plt_index = h->plt.offset / PLT_ENTRY_SIZE - 1; /* first entry reserved. */
3643+ got_offset = (plt_index + 3) * 4; /* 3 reserved ??? */
3644+ got_addr = got_offset;
3645+
3646+ /* For non-PIC objects we need absolute address of the GOT entry. */
3647+ if (!bfd_link_pic (info))
3648+ got_addr += sgotplt->output_section->vma + sgotplt->output_offset;
3649+
3650+ /* Fill in the entry in the procedure linkage table. */
3651+ bfd_put_32 (output_bfd, PLT_ENTRY_WORD_0 + ((got_addr >> 16) & 0xffff),
3652+ splt->contents + h->plt.offset);
3653+ if (bfd_link_pic (info))
3654+ bfd_put_32 (output_bfd, PLT_ENTRY_WORD_1 + (got_addr & 0xffff),
3655+ splt->contents + h->plt.offset + 4);
3656+ else
3657+ bfd_put_32 (output_bfd, PLT_ENTRY_WORD_1_NOPIC + (got_addr & 0xffff),
3658+ splt->contents + h->plt.offset + 4);
3659+ bfd_put_32 (output_bfd, (bfd_vma) PLT_ENTRY_WORD_2,
3660+ splt->contents + h->plt.offset + 8);
3661+ bfd_put_32 (output_bfd, (bfd_vma) PLT_ENTRY_WORD_3,
3662+ splt->contents + h->plt.offset + 12);
3663+
3664+ /* Any additions to the .got section??? */
3665+ /* bfd_put_32 (output_bfd,
3666+ splt->output_section->vma + splt->output_offset + h->plt.offset + 4,
3667+ sgotplt->contents + got_offset); */
3668+
3669+ /* Fill in the entry in the .rela.plt section. */
3670+ rela.r_offset = (sgotplt->output_section->vma
3671+ + sgotplt->output_offset
3672+ + got_offset);
3673+ rela.r_info = ELF64_R_INFO (h->dynindx, R_MICROBLAZE_JUMP_SLOT);
3674+ rela.r_addend = 0;
3675+ loc = srela->contents;
3676+ loc += plt_index * sizeof (Elf64_External_Rela);
3677+ bfd_elf64_swap_reloca_out (output_bfd, &rela, loc);
3678+
3679+ if (!h->def_regular)
3680+ {
3681+ /* Mark the symbol as undefined, rather than as defined in
3682+ the .plt section. Zero the value. */
3683+ sym->st_shndx = SHN_UNDEF;
3684+ sym->st_value = 0;
3685+ }
3686+ }
3687+
3688+ /* h->got.refcount to be checked ? */
3689+ if (h->got.offset != (bfd_vma) -1 &&
3690+ ! ((h->got.offset & 1) ||
3691+ IS_TLS_LD(eh->tls_mask) || IS_TLS_GD(eh->tls_mask)))
3692+ {
3693+ asection *sgot;
3694+ asection *srela;
3695+ bfd_vma offset;
3696+
3697+ /* This symbol has an entry in the global offset table. Set it
3698+ up. */
3699+
3700+ sgot = htab->elf.sgot;
3701+ srela = htab->elf.srelgot;
3702+ BFD_ASSERT (sgot != NULL && srela != NULL);
3703+
3704+ offset = (sgot->output_section->vma + sgot->output_offset
3705+ + (h->got.offset &~ (bfd_vma) 1));
3706+
3707+ /* If this is a -Bsymbolic link, and the symbol is defined
3708+ locally, we just want to emit a RELATIVE reloc. Likewise if
3709+ the symbol was forced to be local because of a version file.
3710+ The entry in the global offset table will already have been
3711+ initialized in the relocate_section function. */
3712+ if (bfd_link_pic (info)
3713+ && ((info->symbolic && h->def_regular)
3714+ || h->dynindx == -1))
3715+ {
3716+ asection *sec = h->root.u.def.section;
3717+ bfd_vma value;
3718+
3719+ value = h->root.u.def.value;
3720+ if (sec->output_section != NULL)
3721+ /* PR 21180: If the output section is NULL, then the symbol is no
3722+ longer needed, and in theory the GOT entry is redundant. But
3723+ it is too late to change our minds now... */
3724+ value += sec->output_section->vma + sec->output_offset;
3725+
3726+ microblaze_elf_output_dynamic_relocation (output_bfd,
3727+ srela, srela->reloc_count++,
3728+ /* symindex= */ 0,
3729+ R_MICROBLAZE_REL, offset,
3730+ value);
3731+ }
3732+ else
3733+ {
3734+ microblaze_elf_output_dynamic_relocation (output_bfd,
3735+ srela, srela->reloc_count++,
3736+ h->dynindx,
3737+ R_MICROBLAZE_GLOB_DAT,
3738+ offset, 0);
3739+ }
3740+
3741+ bfd_put_32 (output_bfd, (bfd_vma) 0,
3742+ sgot->contents + (h->got.offset &~ (bfd_vma) 1));
3743+ }
3744+
3745+ if (h->needs_copy)
3746+ {
3747+ asection *s;
3748+ Elf_Internal_Rela rela;
3749+ bfd_byte *loc;
3750+
3751+ /* This symbols needs a copy reloc. Set it up. */
3752+
3753+ BFD_ASSERT (h->dynindx != -1);
3754+
3755+ rela.r_offset = (h->root.u.def.value
3756+ + h->root.u.def.section->output_section->vma
3757+ + h->root.u.def.section->output_offset);
3758+ rela.r_info = ELF64_R_INFO (h->dynindx, R_MICROBLAZE_COPY);
3759+ rela.r_addend = 0;
3760+ if (h->root.u.def.section == htab->elf.sdynrelro)
3761+ s = htab->elf.sreldynrelro;
3762+ else
3763+ s = htab->elf.srelbss;
3764+ loc = s->contents + s->reloc_count++ * sizeof (Elf32_External_Rela);
3765+ bfd_elf32_swap_reloca_out (output_bfd, &rela, loc);
3766+ }
3767+
3768+ /* Mark some specially defined symbols as absolute. */
3769+ if (h == htab->elf.hdynamic
3770+ || h == htab->elf.hgot
3771+ || h == htab->elf.hplt)
3772+ sym->st_shndx = SHN_ABS;
3773+
3774+ return true;
3775+}
3776+
3777+
3778+/* Finish up the dynamic sections. */
3779+
3780+static bool
3781+microblaze_elf_finish_dynamic_sections (bfd *output_bfd,
3782+ struct bfd_link_info *info)
3783+{
3784+ bfd *dynobj;
3785+ asection *sdyn, *sgot;
3786+ struct elf64_mb_link_hash_table *htab;
3787+
3788+ htab = elf64_mb_hash_table (info);
3789+ if (htab == NULL)
3790+ return false;
3791+
3792+ dynobj = htab->elf.dynobj;
3793+
3794+ sdyn = bfd_get_linker_section (dynobj, ".dynamic");
3795+
3796+ if (htab->elf.dynamic_sections_created)
3797+ {
3798+ asection *splt;
3799+ Elf64_External_Dyn *dyncon, *dynconend;
3800+
3801+ dyncon = (Elf64_External_Dyn *) sdyn->contents;
3802+ dynconend = (Elf64_External_Dyn *) (sdyn->contents + sdyn->size);
3803+ for (; dyncon < dynconend; dyncon++)
3804+ {
3805+ Elf_Internal_Dyn dyn;
3806+ asection *s;
3807+ bool size;
3808+
3809+ bfd_elf64_swap_dyn_in (dynobj, dyncon, &dyn);
3810+
3811+ switch (dyn.d_tag)
3812+ {
3813+ case DT_PLTGOT:
3814+ s = htab->elf.sgotplt;
3815+ size = false;
3816+ break;
3817+
3818+ case DT_PLTRELSZ:
3819+ s = htab->elf.srelplt;
3820+ size = true;
3821+ break;
3822+
3823+ case DT_JMPREL:
3824+ s = htab->elf.srelplt;
3825+ size = false;
3826+ break;
3827+
3828+ default:
3829+ continue;
3830+ }
3831+
3832+ if (s == NULL)
3833+ dyn.d_un.d_val = 0;
3834+ else
3835+ {
3836+ if (!size)
3837+ dyn.d_un.d_ptr = s->output_section->vma + s->output_offset;
3838+ else
3839+ dyn.d_un.d_val = s->size;
3840+ }
3841+ bfd_elf64_swap_dyn_out (output_bfd, &dyn, dyncon);
3842+ }
3843+
3844+ splt = htab->elf.splt;
3845+ BFD_ASSERT (splt != NULL && sdyn != NULL);
3846+
3847+ /* Clear the first entry in the procedure linkage table,
3848+ and put a nop in the last four bytes. */
3849+ if (splt->size > 0)
3850+ {
3851+ memset (splt->contents, 0, PLT_ENTRY_SIZE);
3852+ bfd_put_32 (output_bfd, (bfd_vma) 0x80000000 /* nop. */,
3853+ splt->contents + splt->size - 4);
3854+
3855+ if (splt->output_section != bfd_abs_section_ptr)
3856+ elf_section_data (splt->output_section)->this_hdr.sh_entsize = 4;
3857+ }
3858+ }
3859+
3860+ /* Set the first entry in the global offset table to the address of
3861+ the dynamic section. */
3862+ sgot = htab->elf.sgotplt;
3863+ if (sgot && sgot->size > 0)
3864+ {
3865+ if (sdyn == NULL)
3866+ bfd_put_32 (output_bfd, (bfd_vma) 0, sgot->contents);
3867+ else
3868+ bfd_put_32 (output_bfd,
3869+ sdyn->output_section->vma + sdyn->output_offset,
3870+ sgot->contents);
3871+ elf_section_data (sgot->output_section)->this_hdr.sh_entsize = 4;
3872+ }
3873+
3874+ if (htab->elf.sgot && htab->elf.sgot->size > 0)
3875+ elf_section_data (htab->elf.sgot->output_section)->this_hdr.sh_entsize = 4;
3876+
3877+ return true;
3878+}
3879+
3880+/* Hook called by the linker routine which adds symbols from an object
3881+ file. We use it to put .comm items in .sbss, and not .bss. */
3882+
3883+static bool
3884+microblaze_elf_add_symbol_hook (bfd *abfd,
3885+ struct bfd_link_info *info,
3886+ Elf_Internal_Sym *sym,
3887+ const char **namep ATTRIBUTE_UNUSED,
3888+ flagword *flagsp ATTRIBUTE_UNUSED,
3889+ asection **secp,
3890+ bfd_vma *valp)
3891+{
3892+ if (sym->st_shndx == SHN_COMMON
3893+ && !bfd_link_relocatable (info)
3894+ && sym->st_size <= elf_gp_size (abfd))
3895+ {
3896+ /* Common symbols less than or equal to -G nn bytes are automatically
3897+ put into .sbss. */
3898+ *secp = bfd_make_section_old_way (abfd, ".sbss");
3899+ if (*secp == NULL
3900+ || !bfd_set_section_flags (*secp, SEC_IS_COMMON | SEC_SMALL_DATA))
3901+ return false;
3902+
3903+ *valp = sym->st_size;
3904+ }
3905+
3906+ return true;
3907+}
3908+
3909+#define TARGET_LITTLE_SYM microblaze_elf64_le_vec
3910+#define TARGET_LITTLE_NAME "elf64-microblazeel"
3911+
3912+#define TARGET_BIG_SYM microblaze_elf64_vec
3913+#define TARGET_BIG_NAME "elf64-microblaze"
3914+
3915+#define ELF_ARCH bfd_arch_microblaze
3916+#define ELF_TARGET_ID MICROBLAZE_ELF_DATA
3917+#define ELF_MACHINE_CODE EM_MICROBLAZE
3918+#define ELF_MACHINE_ALT1 EM_MICROBLAZE_OLD
3919+#define ELF_MAXPAGESIZE 0x1000
3920+#define elf_info_to_howto microblaze_elf_info_to_howto
3921+#define elf_info_to_howto_rel NULL
3922+
3923+#define bfd_elf64_bfd_reloc_type_lookup microblaze_elf_reloc_type_lookup
3924+#define bfd_elf64_bfd_is_local_label_name microblaze_elf_is_local_label_name
3925+#define bfd_elf64_new_section_hook microblaze_elf_new_section_hook
3926+#define elf_backend_relocate_section microblaze_elf_relocate_section
3927+#define bfd_elf64_bfd_relax_section microblaze_elf_relax_section
3928+#define bfd_elf64_bfd_merge_private_bfd_data _bfd_generic_verify_endian_match
3929+#define bfd_elf64_bfd_reloc_name_lookup microblaze_elf_reloc_name_lookup
3930+
3931+#define elf_backend_gc_mark_hook microblaze_elf_gc_mark_hook
3932+#define elf_backend_check_relocs microblaze_elf_check_relocs
3933+#define elf_backend_copy_indirect_symbol microblaze_elf_copy_indirect_symbol
3934+#define bfd_elf64_bfd_link_hash_table_create microblaze_elf_link_hash_table_create
3935+#define elf_backend_can_gc_sections 1
3936+#define elf_backend_can_refcount 1
3937+#define elf_backend_want_got_plt 1
3938+#define elf_backend_plt_readonly 1
3939+#define elf_backend_got_header_size 12
3940+#define elf_backend_want_dynrelro 1
3941+#define elf_backend_rela_normal 1
3942+#define elf_backend_dtrel_excludes_plt 1
3943+
3944+#define elf_backend_adjust_dynamic_symbol microblaze_elf_adjust_dynamic_symbol
3945+#define elf_backend_create_dynamic_sections _bfd_elf_create_dynamic_sections
3946+#define elf_backend_finish_dynamic_sections microblaze_elf_finish_dynamic_sections
3947+#define elf_backend_finish_dynamic_symbol microblaze_elf_finish_dynamic_symbol
3948+#define elf_backend_size_dynamic_sections microblaze_elf_size_dynamic_sections
3949+#define elf_backend_add_symbol_hook microblaze_elf_add_symbol_hook
3950+
3951+#include "elf64-target.h"
3952diff --git a/bfd/libbfd.h b/bfd/libbfd.h
3953index ea2507d1879..e74c051e781 100644
3954--- a/bfd/libbfd.h
3955+++ b/bfd/libbfd.h
3956@@ -2991,7 +2991,9 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@",
3957 "BFD_RELOC_MICROBLAZE_32_SYM_OP_SYM",
3958 "BFD_RELOC_MICROBLAZE_32_NONE",
3959 "BFD_RELOC_MICROBLAZE_64_NONE",
3960+ "BFD_RELOC_MICROBLAZE_64",
3961 "BFD_RELOC_MICROBLAZE_64_GOTPC",
3962+ "BFD_RELOC_MICROBLAZE_64_GPC",
3963 "BFD_RELOC_MICROBLAZE_64_GOT",
3964 "BFD_RELOC_MICROBLAZE_64_PLT",
3965 "BFD_RELOC_MICROBLAZE_64_GOTOFF",
3966diff --git a/bfd/reloc.c b/bfd/reloc.c
3967index 5ac8a8536a7..0f99df91299 100644
3968--- a/bfd/reloc.c
3969+++ b/bfd/reloc.c
3970@@ -6875,12 +6875,24 @@ ENUMDOC
3971 done here - only used for relaxing
3972 ENUM
3973 BFD_RELOC_MICROBLAZE_64_NONE
3974+ENUMDOC
3975+ This is a 32 bit reloc that stores the 32 bit pc relative
3976+ value in two words (with an imml instruction). No relocation is
3977+ done here - only used for relaxing
3978+ENUM
3979+ BFD_RELOC_MICROBLAZE_64
3980 ENUMDOC
3981 This is a 64 bit reloc that stores the 32 bit pc relative
3982 value in two words (with an imm instruction). No relocation is
3983 done here - only used for relaxing
3984 ENUM
3985 BFD_RELOC_MICROBLAZE_64_GOTPC
3986+ENUMDOC
3987+ This is a 64 bit reloc that stores the 32 bit pc relative
3988+ value in two words (with an imml instruction). No relocation is
3989+ done here - only used for relaxing
3990+ENUM
3991+ BFD_RELOC_MICROBLAZE_64_GPC
3992 ENUMDOC
3993 This is a 64 bit reloc that stores the 32 bit pc relative
3994 value in two words (with an imm instruction). The relocation is
3995diff --git a/bfd/targets.c b/bfd/targets.c
3996index 3284bb88aa8..6e93cb2f995 100644
3997--- a/bfd/targets.c
3998+++ b/bfd/targets.c
3999@@ -791,6 +791,8 @@ extern const bfd_target mep_elf32_le_vec;
4000 extern const bfd_target metag_elf32_vec;
4001 extern const bfd_target microblaze_elf32_vec;
4002 extern const bfd_target microblaze_elf32_le_vec;
4003+extern const bfd_target microblaze_elf64_vec;
4004+extern const bfd_target microblaze_elf64_le_vec;
4005 extern const bfd_target mips_ecoff_be_vec;
4006 extern const bfd_target mips_ecoff_le_vec;
4007 extern const bfd_target mips_ecoff_bele_vec;
4008@@ -1153,6 +1155,10 @@ static const bfd_target * const _bfd_target_vector[] =
4009
4010 &metag_elf32_vec,
4011
4012+#ifdef BFD64
4013+ &microblaze_elf64_vec,
4014+ &microblaze_elf64_le_vec,
4015+#endif
4016 &microblaze_elf32_vec,
4017
4018 &mips_ecoff_be_vec,
4019diff --git a/gas/config/tc-microblaze.c b/gas/config/tc-microblaze.c
4020index 086f8704156..a6f12dda54a 100644
4021--- a/gas/config/tc-microblaze.c
4022+++ b/gas/config/tc-microblaze.c
4023@@ -35,10 +35,13 @@
4024 #define streq(a,b) (strcmp (a, b) == 0)
4025 #endif
4026
4027+static int microblaze_arch_size = 0;
4028+
4029 #define OPTION_EB (OPTION_MD_BASE + 0)
4030 #define OPTION_EL (OPTION_MD_BASE + 1)
4031 #define OPTION_LITTLE (OPTION_MD_BASE + 2)
4032 #define OPTION_BIG (OPTION_MD_BASE + 3)
4033+#define OPTION_M64 (OPTION_MD_BASE + 4)
4034
4035 void microblaze_generate_symbol (char *sym);
4036 static bool check_spl_reg (unsigned *);
4037@@ -91,6 +94,7 @@ const char FLT_CHARS[] = "rRsSfFdDxXpP";
4038 #define TLSTPREL_OFFSET 16
4039 #define TEXT_OFFSET 17
4040 #define TEXT_PC_OFFSET 18
4041+#define DEFINED_64_OFFSET 19
4042
4043 /* Initialize the relax table. */
4044 const relax_typeS md_relax_table[] =
4045@@ -113,7 +117,9 @@ const relax_typeS md_relax_table[] =
4046 { 0x7fffffff, 0x80000000, INST_WORD_SIZE*2, 0 }, /* 15: TLSGOTTPREL_OFFSET. */
4047 { 0x7fffffff, 0x80000000, INST_WORD_SIZE*2, 0 }, /* 16: TLSTPREL_OFFSET. */
4048 { 0x7fffffff, 0x80000000, INST_WORD_SIZE*2, 0 }, /* 17: TEXT_OFFSET. */
4049- { 0x7fffffff, 0x80000000, INST_WORD_SIZE*2, 0 } /* 18: TEXT_PC_OFFSET. */
4050+ { 0x7fffffff, 0x80000000, INST_WORD_SIZE*2, 0 }, /* 18: TEXT_PC_OFFSET. */
4051+// { 0x7fffffff, 0x80000000, INST_WORD_SIZE*2, 0 } /* 16: TLSTPREL_OFFSET. */
4052+ { 0x7fffffffffffffff, 0x8000000000000000, INST_WORD_SIZE, 0 } /* 17: DEFINED_64_OFFSET. */
4053 };
4054
4055 static htab_t opcode_hash_control; /* Opcode mnemonics. */
4056@@ -393,7 +399,8 @@ const pseudo_typeS md_pseudo_table[] =
4057 {"data32", cons, 4}, /* Same as word. */
4058 {"ent", s_func, 0}, /* Treat ent as function entry point. */
4059 {"end", microblaze_s_func, 1}, /* Treat end as function end point. */
4060- {"gpword", s_rva, 4}, /* gpword label => store resolved label address in data section. */
4061+ {"gpword", s_rva, 8}, /* gpword label => store resolved label address in data section. */
4062+ {"gpdword", s_rva, 8}, /* gpword label => store resolved label address in data section. */
4063 {"weakext", microblaze_s_weakext, 0},
4064 {"rodata", microblaze_s_rdata, 0},
4065 {"sdata2", microblaze_s_rdata, 1},
4066@@ -402,6 +409,7 @@ const pseudo_typeS md_pseudo_table[] =
4067 {"sbss", microblaze_s_bss, 1},
4068 {"text", microblaze_s_text, 0},
4069 {"word", cons, 4},
4070+ {"dword", cons, 8},
4071 {"frame", s_ignore, 0},
4072 {"mask", s_ignore, 0}, /* Emitted by gcc. */
4073 {NULL, NULL, 0}
4074@@ -773,6 +781,74 @@ parse_imm (char * s, expressionS * e, offsetT min, offsetT max)
4075 return new_pointer;
4076 }
4077
4078+ static char *
4079+parse_imml (char * s, expressionS * e, long min, long max)
4080+{
4081+ char *new_pointer;
4082+ char *atp;
4083+ int itype, ilen;
4084+
4085+ ilen = 0;
4086+
4087+ /* Find the start of "@GOT" or "@PLT" suffix (if any) */
4088+ for (atp = s; *atp != '@'; atp++)
4089+ if (is_end_of_line[(unsigned char) *atp])
4090+ break;
4091+
4092+ if (*atp == '@')
4093+ {
4094+ itype = match_imm (atp + 1, &ilen);
4095+ if (itype != 0)
4096+ {
4097+ *atp = 0;
4098+ e->X_md = itype;
4099+ }
4100+ else
4101+ {
4102+ atp = NULL;
4103+ e->X_md = 0;
4104+ ilen = 0;
4105+ }
4106+ *atp = 0;
4107+ }
4108+ else
4109+ {
4110+ atp = NULL;
4111+ e->X_md = 0;
4112+ }
4113+
4114+ if (atp && !GOT_symbol)
4115+ {
4116+ GOT_symbol = symbol_find_or_make (GOT_SYMBOL_NAME);
4117+ }
4118+
4119+ new_pointer = parse_exp (s, e);
4120+
4121+ if (!GOT_symbol && ! strncmp (s, GOT_SYMBOL_NAME, 20))
4122+ {
4123+ GOT_symbol = symbol_find_or_make (GOT_SYMBOL_NAME);
4124+ }
4125+
4126+ if (e->X_op == O_absent)
4127+ ; /* An error message has already been emitted. */
4128+ else if ((e->X_op != O_constant && e->X_op != O_symbol) )
4129+ as_fatal (_("operand must be a constant or a label"));
4130+ else if ((e->X_op == O_constant) && ((long) e->X_add_number < min
4131+ || (long) e->X_add_number > max))
4132+ {
4133+ as_fatal (_("operand must be absolute in range %ld..%ld, not %ld"),
4134+ min, max, (long) e->X_add_number);
4135+ }
4136+
4137+ if (atp)
4138+ {
4139+ *atp = '@'; /* restore back (needed?) */
4140+ if (new_pointer >= atp)
4141+ new_pointer += ilen + 1; /* sizeof (imm_suffix) + 1 for '@' */
4142+ }
4143+ return new_pointer;
4144+}
4145+
4146 static char *
4147 check_got (int * got_type, int * got_len)
4148 {
4149@@ -827,7 +903,7 @@ check_got (int * got_type, int * got_len)
4150 extern bfd_reloc_code_real_type
4151 parse_cons_expression_microblaze (expressionS *exp, int size)
4152 {
4153- if (size == 4)
4154+ if (size == 4 || (microblaze_arch_size == 64 && size == 8))
4155 {
4156 /* Handle @GOTOFF et.al. */
4157 char *save, *gotfree_copy;
4158@@ -859,6 +935,7 @@ parse_cons_expression_microblaze (expressionS *exp, int size)
4159
4160 static const char * str_microblaze_ro_anchor = "RO";
4161 static const char * str_microblaze_rw_anchor = "RW";
4162+static const char * str_microblaze_64 = "64";
4163
4164 static bool
4165 check_spl_reg (unsigned * reg)
4166@@ -920,6 +997,7 @@ md_assemble (char * str)
4167 unsigned int immed = 0, immed2 = 0, temp;
4168 expressionS exp;
4169 char name[20];
4170+ long immedl;
4171
4172 /* Drop leading whitespace. */
4173 while (ISSPACE (* str))
4174@@ -1106,6 +1184,33 @@ md_assemble (char * str)
4175 inst |= (immed << IMM_LOW) & IMM_MASK;
4176 }
4177 }
4178+#if 0 //revisit
4179+ else if (streq (name, "lli") || streq (name, "sli"))
4180+ {
4181+ temp = immed & 0xFFFFFFFFFFFF8000;
4182+ if ((temp != 0) && (temp != 0xFFFFFFFFFFFF8000))
4183+ {
4184+ /* Needs an immediate inst. */
4185+ opcode1 = (struct op_code_struct *) str_hash_find (opcode_hash_control, "imml");
4186+ if (opcode1 == NULL)
4187+ {
4188+ as_bad (_("unknown opcode \"%s\""), "imml");
4189+ return;
4190+ }
4191+
4192+ inst1 = opcode1->bit_sequence;
4193+ inst1 |= ((immedl & 0xFFFFFFFFFFFF0000L) >> 16) & IMML_MASK;
4194+ output[0] = INST_BYTE0 (inst1);
4195+ output[1] = INST_BYTE1 (inst1);
4196+ output[2] = INST_BYTE2 (inst1);
4197+ output[3] = INST_BYTE3 (inst1);
4198+ output = frag_more (isize);
4199+ }
4200+ inst |= (reg1 << RD_LOW) & RD_MASK;
4201+ inst |= (reg2 << RA_LOW) & RA_MASK;
4202+ inst |= (immed << IMM_LOW) & IMM_MASK;
4203+ }
4204+#endif
4205 else
4206 {
4207 temp = immed & 0xFFFF8000;
4208@@ -1135,7 +1240,7 @@ md_assemble (char * str)
4209 }
4210 break;
4211
4212- case INST_TYPE_RD_R1_IMM5:
4213+ case INST_TYPE_RD_R1_IMMS:
4214 if (strcmp (op_end, ""))
4215 op_end = parse_reg (op_end + 1, &reg1); /* Get rd. */
4216 else
4217@@ -1169,16 +1274,22 @@ md_assemble (char * str)
4218 immed = exp.X_add_number;
4219 }
4220
4221- if (immed != (immed % 32))
4222+ if ((immed != (immed % 32)) &&
4223+ (opcode->instr == bslli || opcode->instr == bsrai || opcode->instr == bsrli))
4224 {
4225 as_warn (_("Shift value > 32. using <value %% 32>"));
4226 immed = immed % 32;
4227 }
4228+ else if (immed != (immed % 64))
4229+ {
4230+ as_warn (_("Shift value > 64. using <value %% 64>"));
4231+ immed = immed % 64;
4232+ }
4233 inst |= (reg1 << RD_LOW) & RD_MASK;
4234 inst |= (reg2 << RA_LOW) & RA_MASK;
4235- inst |= (immed << IMM_LOW) & IMM5_MASK;
4236+ inst |= (immed << IMM_LOW) & IMM6_MASK;
4237 break;
4238- case INST_TYPE_RD_R1_IMM5_IMM5:
4239+ case INST_TYPE_RD_R1_IMMW_IMMS:
4240 if (strcmp (op_end, ""))
4241 op_end = parse_reg (op_end + 1, &reg1); /* Get rd. */
4242 else
4243@@ -1202,7 +1313,7 @@ md_assemble (char * str)
4244
4245 /* Width immediate value. */
4246 if (strcmp (op_end, ""))
4247- op_end = parse_imm (op_end + 1, &exp, MIN_IMM_WIDTH, MAX_IMM_WIDTH);
4248+ op_end = parse_imm (op_end + 1, &exp, MIN_IMM, MAX_IMM);
4249 else
4250 as_fatal (_("Error in statement syntax"));
4251 if (exp.X_op != O_constant)
4252@@ -1214,6 +1325,8 @@ md_assemble (char * str)
4253 immed = exp.X_add_number;
4254 if (opcode->instr == bsefi && immed > 31)
4255 as_fatal (_("Width value must be less than 32"));
4256+ else if (opcode->instr == bslefi && immed > 63)
4257+ as_fatal (_("Width value must be less than 64"));
4258
4259 /* Shift immediate value. */
4260 if (strcmp (op_end, ""))
4261@@ -1221,32 +1334,40 @@ md_assemble (char * str)
4262 else
4263 as_fatal (_("Error in statement syntax"));
4264 if (exp.X_op != O_constant)
4265- {
4266+ {
4267 as_warn (_("Symbol used as immediate shift value for bit field instruction"));
4268 immed2 = 0;
4269 }
4270 else
4271- {
4272+ {
4273 output = frag_more (isize);
4274 immed2 = exp.X_add_number;
4275- }
4276- if (immed2 != (immed2 % 32))
4277- {
4278- as_warn (_("Shift value greater than 32. using <value %% 32>"));
4279+ }
4280+ if ((immed2 != (immed2 % 32)) && (opcode->instr == bsefi || opcode->instr == bsifi))
4281+ {
4282+
4283+ as_warn (_("Shift value greater than 32. using <value %% 32>"));
4284 immed2 = immed2 % 32;
4285 }
4286+ else if (immed2 != (immed2 % 64))
4287+ {
4288+ as_warn (_("Shift value greater than 64. using <value %% 64>"));
4289+ immed2 = immed2 % 64;
4290+ }
4291
4292 /* Check combined value. */
4293- if (immed + immed2 > 32)
4294+ if ((immed + immed2 > 32) && (opcode->instr == bsefi || opcode->instr == bsifi))
4295 as_fatal (_("Width value + shift value must not be greater than 32"));
4296
4297+ else if (immed + immed2 > 64)
4298+ as_fatal (_("Width value + shift value must not be greater than 64"));
4299 inst |= (reg1 << RD_LOW) & RD_MASK;
4300 inst |= (reg2 << RA_LOW) & RA_MASK;
4301- if (opcode->instr == bsefi)
4302- inst |= (immed & IMM5_MASK) << IMM_WIDTH_LOW; /* bsefi */
4303+ if (opcode->instr == bsefi || opcode->instr == bslefi)
4304+ inst |= (immed & IMM6_MASK) << IMM_WIDTH_LOW; /* bsefi or bslefi */
4305 else
4306- inst |= ((immed + immed2 - 1) & IMM5_MASK) << IMM_WIDTH_LOW; /* bsifi */
4307- inst |= (immed2 << IMM_LOW) & IMM5_MASK;
4308+ inst |= ((immed + immed2 - 1) & IMM6_MASK) << IMM_WIDTH_LOW; /* bsifi or bslifi */
4309+ inst |= (immed2 << IMM_LOW) & IMM6_MASK;
4310 break;
4311 case INST_TYPE_R1_R2:
4312 if (strcmp (op_end, ""))
4313@@ -1820,6 +1941,143 @@ md_assemble (char * str)
4314 }
4315 inst |= (immed << IMM_MBAR);
4316 break;
4317+ /* For 64-bit instructions */
4318+ case INST_TYPE_RD_R1_IMML:
4319+ if (strcmp (op_end, ""))
4320+ op_end = parse_reg (op_end + 1, &reg1); /* Get rd. */
4321+ else
4322+ {
4323+ as_fatal (_("Error in statement syntax"));
4324+ reg1 = 0;
4325+ }
4326+ if (strcmp (op_end, ""))
4327+ op_end = parse_reg (op_end + 1, &reg2); /* Get r1. */
4328+ else
4329+ {
4330+ as_fatal (_("Error in statement syntax"));
4331+ reg2 = 0;
4332+ }
4333+ if (strcmp (op_end, ""))
4334+ op_end = parse_imml (op_end + 1, & exp, MIN_IMML, MAX_IMML);
4335+ else
4336+ as_fatal (_("Error in statement syntax"));
4337+
4338+ /* Check for spl registers. */
4339+ if (check_spl_reg (& reg1))
4340+ as_fatal (_("Cannot use special register with this instruction"));
4341+ if (check_spl_reg (& reg2))
4342+ as_fatal (_("Cannot use special register with this instruction"));
4343+
4344+ if (exp.X_op != O_constant)
4345+ {
4346+ char *opc = NULL;
4347+ //char *opc = str_microblaze_64;
4348+ relax_substateT subtype;
4349+
4350+ if (exp.X_md != 0)
4351+ subtype = get_imm_otype(exp.X_md);
4352+ else
4353+ subtype = opcode->inst_offset_type;
4354+
4355+ output = frag_var (rs_machine_dependent,
4356+ isize * 2, /* maxm of 2 words. */
4357+ isize * 2, /* minm of 2 words. */
4358+ subtype, /* PC-relative or not. */
4359+ exp.X_add_symbol,
4360+ exp.X_add_number,
4361+ (char *) opc);
4362+ immedl = 0L;
4363+ }
4364+ else
4365+ {
4366+ output = frag_more (isize);
4367+ immedl = exp.X_add_number;
4368+
4369+ opcode1 = (struct op_code_struct *) str_hash_find (opcode_hash_control, "imml");
4370+ if (opcode1 == NULL)
4371+ {
4372+ as_bad (_("unknown opcode \"%s\""), "imml");
4373+ return;
4374+ }
4375+
4376+ inst1 = opcode1->bit_sequence;
4377+ inst1 |= ((immedl & 0xFFFFFFFFFFFF0000L) >> 16) & IMML_MASK;
4378+ output[0] = INST_BYTE0 (inst1);
4379+ output[1] = INST_BYTE1 (inst1);
4380+ output[2] = INST_BYTE2 (inst1);
4381+ output[3] = INST_BYTE3 (inst1);
4382+ output = frag_more (isize);
4383+ }
4384+
4385+ inst |= (reg1 << RD_LOW) & RD_MASK;
4386+ inst |= (reg2 << RA_LOW) & RA_MASK;
4387+ inst |= (immedl << IMM_LOW) & IMM_MASK;
4388+ break;
4389+
4390+ case INST_TYPE_R1_IMML:
4391+ if (strcmp (op_end, ""))
4392+ op_end = parse_reg (op_end + 1, &reg1); /* Get r1. */
4393+ else
4394+ {
4395+ as_fatal (_("Error in statement syntax"));
4396+ reg1 = 0;
4397+ }
4398+ if (strcmp (op_end, ""))
4399+ op_end = parse_imml (op_end + 1, & exp, MIN_IMML, MAX_IMML);
4400+ else
4401+ as_fatal (_("Error in statement syntax"));
4402+
4403+ /* Check for spl registers. */
4404+ if (check_spl_reg (&reg1))
4405+ as_fatal (_("Cannot use special register with this instruction"));
4406+
4407+ if (exp.X_op != O_constant)
4408+ {
4409+ //char *opc = NULL;
4410+ char *opc = str_microblaze_64;
4411+ relax_substateT subtype;
4412+
4413+ if (exp.X_md != 0)
4414+ subtype = get_imm_otype(exp.X_md);
4415+ else
4416+ subtype = opcode->inst_offset_type;
4417+
4418+ output = frag_var (rs_machine_dependent,
4419+ isize * 2, /* maxm of 2 words. */
4420+ isize * 2, /* minm of 2 words. */
4421+ subtype, /* PC-relative or not. */
4422+ exp.X_add_symbol,
4423+ exp.X_add_number,
4424+ (char *) opc);
4425+ immedl = 0L;
4426+ }
4427+ else
4428+ {
4429+ output = frag_more (isize);
4430+ immedl = exp.X_add_number;
4431+ opcode1 = (struct op_code_struct *) str_hash_find (opcode_hash_control, "imml");
4432+ if (opcode1 == NULL)
4433+ {
4434+ as_bad (_("unknown opcode \"%s\""), "imml");
4435+ return;
4436+ }
4437+
4438+ inst1 = opcode1->bit_sequence;
4439+ inst1 |= ((immedl & 0xFFFFFFFFFFFF0000L) >> 16) & IMML_MASK;
4440+ output[0] = INST_BYTE0 (inst1);
4441+ output[1] = INST_BYTE1 (inst1);
4442+ output[2] = INST_BYTE2 (inst1);
4443+ output[3] = INST_BYTE3 (inst1);
4444+ output = frag_more (isize);
4445+ }
4446+
4447+ inst |= (reg1 << RA_LOW) & RA_MASK;
4448+ inst |= (immedl << IMM_LOW) & IMM_MASK;
4449+ break;
4450+
4451+ case INST_TYPE_IMML:
4452+ as_fatal (_("An IMML instruction should not be present in the .s file"));
4453+ break;
4454
4455 default:
4456 as_fatal (_("unimplemented opcode \"%s\""), name);
4457@@ -1927,6 +2185,7 @@ struct option md_longopts[] =
4458 {"EL", no_argument, NULL, OPTION_EL},
4459 {"mlittle-endian", no_argument, NULL, OPTION_LITTLE},
4460 {"mbig-endian", no_argument, NULL, OPTION_BIG},
4461+ {"m64", no_argument, NULL, OPTION_M64},
4462 { NULL, no_argument, NULL, 0}
4463 };
4464
4465@@ -1971,13 +2230,23 @@ md_convert_frag (bfd * abfd ATTRIBUTE_UNUSED,
4466 fragP->fr_fix += INST_WORD_SIZE * 2;
4467 fragP->fr_var = 0;
4468 break;
4469+ case DEFINED_64_OFFSET:
4470+ if (fragP->fr_symbol == GOT_symbol)
4471+ fix_new (fragP, fragP->fr_fix, INST_WORD_SIZE, fragP->fr_symbol,
4472+ fragP->fr_offset, true, BFD_RELOC_MICROBLAZE_64_GPC);
4473+ else
4474+ fix_new (fragP, fragP->fr_fix, INST_WORD_SIZE, fragP->fr_symbol,
4475+ fragP->fr_offset, true, BFD_RELOC_MICROBLAZE_64);
4476+ fragP->fr_fix += INST_WORD_SIZE * 2;
4477+ fragP->fr_var = 0;
4478+ break;
4479 case DEFINED_ABS_SEGMENT:
4480 if (fragP->fr_symbol == GOT_symbol)
4481 fix_new (fragP, fragP->fr_fix, INST_WORD_SIZE * 2, fragP->fr_symbol,
4482 fragP->fr_offset, true, BFD_RELOC_MICROBLAZE_64_GOTPC);
4483 else
4484 fix_new (fragP, fragP->fr_fix, INST_WORD_SIZE * 2, fragP->fr_symbol,
4485- fragP->fr_offset, false, BFD_RELOC_64);
4486+ fragP->fr_offset, true, BFD_RELOC_64);
4487 fragP->fr_fix += INST_WORD_SIZE * 2;
4488 fragP->fr_var = 0;
4489 break;
4490@@ -2198,23 +2467,38 @@ md_apply_fix (fixS * fixP,
4491 case BFD_RELOC_64_PCREL:
4492 case BFD_RELOC_64:
4493 case BFD_RELOC_MICROBLAZE_64_TEXTREL:
4494+ case BFD_RELOC_MICROBLAZE_64:
4495 /* Add an imm instruction. First save the current instruction. */
4496 for (i = 0; i < INST_WORD_SIZE; i++)
4497 buf[i + INST_WORD_SIZE] = buf[i];
4498+ if (fixP->fx_r_type == BFD_RELOC_MICROBLAZE_64)
4499+ {
4500+ /* Generate the imm instruction. */
4501+ opcode1 = (struct op_code_struct *) str_hash_find (opcode_hash_control, "imml");
4502+ if (opcode1 == NULL)
4503+ {
4504+ as_bad (_("unknown opcode \"%s\""), "imml");
4505+ return;
4506+ }
4507
4508- /* Generate the imm instruction. */
4509- opcode1
4510- = (struct op_code_struct *) str_hash_find (opcode_hash_control, "imm");
4511- if (opcode1 == NULL)
4512- {
4513- as_bad (_("unknown opcode \"%s\""), "imm");
4514- return;
4515- }
4516-
4517- inst1 = opcode1->bit_sequence;
4518- if (fixP->fx_addsy == NULL || S_IS_DEFINED (fixP->fx_addsy))
4519- inst1 |= ((val & 0xFFFF0000) >> 16) & IMM_MASK;
4520-
4521+ inst1 = opcode1->bit_sequence;
4522+ if (fixP->fx_addsy == NULL || S_IS_DEFINED (fixP->fx_addsy))
4523+ inst1 |= ((val & 0xFFFFFFFFFFFF0000L) >> 16) & IMML_MASK;
4524+ }
4525+ else
4526+ {
4527+ /* Generate the imm instruction. */
4528+ opcode1 = (struct op_code_struct *) str_hash_find (opcode_hash_control, "imm");
4529+ if (opcode1 == NULL)
4530+ {
4531+ as_bad (_("unknown opcode \"%s\""), "imm");
4532+ return;
4533+ }
4534+
4535+ inst1 = opcode1->bit_sequence;
4536+ if (fixP->fx_addsy == NULL || S_IS_DEFINED (fixP->fx_addsy))
4537+ inst1 |= ((val & 0xFFFF0000) >> 16) & IMM_MASK;
4538+ }
4539 buf[0] = INST_BYTE0 (inst1);
4540 buf[1] = INST_BYTE1 (inst1);
4541 buf[2] = INST_BYTE2 (inst1);
4542@@ -2243,6 +2527,7 @@ md_apply_fix (fixS * fixP,
4543 /* Fall through. */
4544
4545 case BFD_RELOC_MICROBLAZE_64_GOTPC:
4546+ case BFD_RELOC_MICROBLAZE_64_GPC:
4547 case BFD_RELOC_MICROBLAZE_64_GOT:
4548 case BFD_RELOC_MICROBLAZE_64_PLT:
4549 case BFD_RELOC_MICROBLAZE_64_GOTOFF:
4550@@ -2250,13 +2535,17 @@ md_apply_fix (fixS * fixP,
4551 /* Add an imm instruction. First save the current instruction. */
4552 for (i = 0; i < INST_WORD_SIZE; i++)
4553 buf[i + INST_WORD_SIZE] = buf[i];
4554-
4555 /* Generate the imm instruction. */
4556- opcode1
4557- = (struct op_code_struct *) str_hash_find (opcode_hash_control, "imm");
4558+ if (fixP->fx_r_type == BFD_RELOC_MICROBLAZE_64_GPC)
4559+ opcode1 = (struct op_code_struct *) str_hash_find (opcode_hash_control, "imml");
4560+ else
4561+ opcode1 = (struct op_code_struct *) str_hash_find (opcode_hash_control, "imm");
4562 if (opcode1 == NULL)
4563 {
4564- as_bad (_("unknown opcode \"%s\""), "imm");
4565+ if (fixP->fx_r_type == BFD_RELOC_MICROBLAZE_64_GPC)
4566+ as_bad (_("unknown opcode \"%s\""), "imml");
4567+ else
4568+ as_bad (_("unknown opcode \"%s\""), "imm");
4569 return;
4570 }
4571
4572@@ -2280,6 +2569,8 @@ md_apply_fix (fixS * fixP,
4573 moves code around due to relaxing. */
4574 if (fixP->fx_r_type == BFD_RELOC_64_PCREL)
4575 fixP->fx_r_type = BFD_RELOC_MICROBLAZE_64_NONE;
4576+ if (fixP->fx_r_type == BFD_RELOC_MICROBLAZE_64)
4577+ fixP->fx_r_type = BFD_RELOC_MICROBLAZE_64_NONE;
4578 else if (fixP->fx_r_type == BFD_RELOC_32)
4579 fixP->fx_r_type = BFD_RELOC_MICROBLAZE_32_NONE;
4580 else
4581@@ -2323,6 +2614,32 @@ md_estimate_size_before_relax (fragS * fragP,
4582 as_bad (_("Absolute PC-relative value in relaxation code. Assembler error....."));
4583 abort ();
4584 }
4585+ else if (S_GET_SEGMENT (fragP->fr_symbol) == segment_type
4586+ && !S_IS_WEAK (fragP->fr_symbol))
4587+ {
4588+ if (fragP->fr_opcode != NULL) {
4589+ if(streq (fragP->fr_opcode, str_microblaze_64))
4590+ {
4591+ /* Used as an absolute value. */
4592+ fragP->fr_subtype = DEFINED_64_OFFSET;
4593+ /* Variable part does not change. */
4594+ fragP->fr_var = INST_WORD_SIZE;
4595+ }
4596+ else
4597+ {
4598+ fragP->fr_subtype = DEFINED_PC_OFFSET;
4599+ /* Don't know now whether we need an imm instruction. */
4600+ fragP->fr_var = INST_WORD_SIZE;
4601+ }
4602+ }
4603+ else
4604+ {
4605+ fragP->fr_subtype = DEFINED_PC_OFFSET;
4606+ /* Don't know now whether we need an imm instruction. */
4607+ fragP->fr_var = INST_WORD_SIZE;
4608+ }
4609+ }
4610+ #if 0
4611 else if (S_GET_SEGMENT (fragP->fr_symbol) == segment_type &&
4612 !S_IS_WEAK (fragP->fr_symbol))
4613 {
4614@@ -2330,6 +2647,7 @@ md_estimate_size_before_relax (fragS * fragP,
4615 /* Don't know now whether we need an imm instruction. */
4616 fragP->fr_var = INST_WORD_SIZE;
4617 }
4618+#endif
4619 else if (S_IS_DEFINED (fragP->fr_symbol)
4620 && (((S_GET_SEGMENT (fragP->fr_symbol))->flags & SEC_CODE) == 0))
4621 {
4622@@ -2432,6 +2750,7 @@ md_estimate_size_before_relax (fragS * fragP,
4623 case TLSLD_OFFSET:
4624 case TLSTPREL_OFFSET:
4625 case TLSDTPREL_OFFSET:
4626+ case DEFINED_64_OFFSET:
4627 fragP->fr_var = INST_WORD_SIZE*2;
4628 break;
4629 case DEFINED_RO_SEGMENT:
4630@@ -2485,7 +2804,7 @@ md_pcrel_from_section (fixS * fixp, segT sec ATTRIBUTE_UNUSED)
4631 else
4632 {
4633 /* The case where we are going to resolve things... */
4634- if (fixp->fx_r_type == BFD_RELOC_64_PCREL)
4635+ if (fixp->fx_r_type == BFD_RELOC_64_PCREL ||fixp->fx_r_type == BFD_RELOC_MICROBLAZE_64)
4636 return fixp->fx_where + fixp->fx_frag->fr_address + INST_WORD_SIZE;
4637 else
4638 return fixp->fx_where + fixp->fx_frag->fr_address;
4639@@ -2518,6 +2837,8 @@ tc_gen_reloc (asection * section ATTRIBUTE_UNUSED, fixS * fixp)
4640 case BFD_RELOC_MICROBLAZE_32_RWSDA:
4641 case BFD_RELOC_MICROBLAZE_32_SYM_OP_SYM:
4642 case BFD_RELOC_MICROBLAZE_64_GOTPC:
4643+ case BFD_RELOC_MICROBLAZE_64_GPC:
4644+ case BFD_RELOC_MICROBLAZE_64:
4645 case BFD_RELOC_MICROBLAZE_64_GOT:
4646 case BFD_RELOC_MICROBLAZE_64_PLT:
4647 case BFD_RELOC_MICROBLAZE_64_GOTOFF:
4648@@ -2578,6 +2899,18 @@ tc_gen_reloc (asection * section ATTRIBUTE_UNUSED, fixS * fixp)
4649 return rel;
4650 }
4651
4652+/* Called by TARGET_FORMAT. */
4653+const char *
4654+microblaze_target_format (void)
4655+{
4656+
4657+ if (microblaze_arch_size == 64)
4658+ return "elf64-microblazeel";
4659+ else
4660+ return target_big_endian ? "elf32-microblaze" : "elf32-microblazeel";
4661+}
4662+
4663+
4664 int
4665 md_parse_option (int c, const char * arg ATTRIBUTE_UNUSED)
4666 {
4667@@ -2591,6 +2924,10 @@ md_parse_option (int c, const char * arg ATTRIBUTE_UNUSED)
4668 case OPTION_LITTLE:
4669 target_big_endian = 0;
4670 break;
4671+ case OPTION_M64:
4672+ //if (arg != NULL && strcmp (arg, "64") == 0)
4673+ microblaze_arch_size = 64;
4674+ break;
4675 default:
4676 return 0;
4677 }
4678@@ -2606,6 +2943,7 @@ md_show_usage (FILE * stream ATTRIBUTE_UNUSED)
4679 fprintf (stream, _(" MicroBlaze specific assembler options:\n"));
4680 fprintf (stream, " -%-23s%s\n", "mbig-endian", N_("assemble for a big endian cpu"));
4681 fprintf (stream, " -%-23s%s\n", "mlittle-endian", N_("assemble for a little endian cpu"));
4682+ fprintf (stream, " -%-23s%s\n", "m64", N_("generate 64-bit elf"));
4683 }
4684
4685
4686@@ -2643,7 +2981,10 @@ cons_fix_new_microblaze (fragS * frag,
4687 r = BFD_RELOC_32;
4688 break;
4689 case 8:
4690- r = BFD_RELOC_64;
4691+ if (microblaze_arch_size == 64)
4692+ r = BFD_RELOC_32;
4693+ else
4694+ r = BFD_RELOC_64;
4695 break;
4696 default:
4697 as_bad (_("unsupported BFD relocation size %u"), size);
4698diff --git a/gas/config/tc-microblaze.h b/gas/config/tc-microblaze.h
4699index 36f56725c46..5a97b460212 100644
4700--- a/gas/config/tc-microblaze.h
4701+++ b/gas/config/tc-microblaze.h
4702@@ -81,7 +81,9 @@ extern const struct relax_type md_relax_table[];
4703
4704 #ifdef OBJ_ELF
4705
4706-#define TARGET_FORMAT (target_big_endian ? "elf32-microblaze" : "elf32-microblazeel")
4707+#define TARGET_FORMAT microblaze_target_format()
4708+extern const char *microblaze_target_format (void);
4709+//#define TARGET_FORMAT (target_big_endian ? "elf32-microblaze" : "elf32-microblazeel")
4710
4711 #define ELF_TC_SPECIAL_SECTIONS \
4712 { ".sdata", SHT_PROGBITS, SHF_ALLOC + SHF_WRITE }, \
4713diff --git a/include/elf/common.h b/include/elf/common.h
4714index e4bc53e35b4..1ad565adf7a 100644
4715--- a/include/elf/common.h
4716+++ b/include/elf/common.h
4717@@ -360,6 +360,7 @@
4718 #define EM_U16_U8CORE 260 /* LAPIS nX-U16/U8 */
4719 #define EM_TACHYUM 261 /* Tachyum */
4720 #define EM_56800EF 262 /* NXP 56800EF Digital Signal Controller (DSC) */
4721+#define EM_MB_64 263 /* Xilinx MicroBlaze 32-bit RISC soft processor core */
4722
4723 /* If it is necessary to assign new unofficial EM_* values, please pick large
4724 random numbers (0x8523, 0xa7f2, etc.) to minimize the chances of collision
4725diff --git a/include/elf/microblaze.h b/include/elf/microblaze.h
4726index a2e1ce4580f..79799b86a49 100644
4727--- a/include/elf/microblaze.h
4728+++ b/include/elf/microblaze.h
4729@@ -62,6 +62,8 @@ START_RELOC_NUMBERS (elf_microblaze_reloc_type)
4730 RELOC_NUMBER (R_MICROBLAZE_TEXTREL_64, 31) /* TEXT Entry offset 64-bit. */
4731 RELOC_NUMBER (R_MICROBLAZE_TEXTREL_32_LO, 32) /* TEXT Entry offset 32-bit. */
4732 RELOC_NUMBER (R_MICROBLAZE_32_NONE, 33)
4733+ RELOC_NUMBER (R_MICROBLAZE_IMML_64, 34)
4734+ RELOC_NUMBER (R_MICROBLAZE_GPC_64, 35) /* GOT entry offset. */
4735
4736 END_RELOC_NUMBERS (R_MICROBLAZE_max)
4737
4738diff --git a/ld/Makefile.am b/ld/Makefile.am
4739index d31021c13e2..bd1a2e5a625 100644
4740--- a/ld/Makefile.am
4741+++ b/ld/Makefile.am
4742@@ -418,6 +418,8 @@ ALL_64_EMULATION_SOURCES = \
4743 eelf32ltsmipn32.c \
4744 eelf32ltsmipn32_fbsd.c \
4745 eelf32mipswindiss.c \
4746+ eelf64microblazeel.c \
4747+ eelf64microblaze.c \
4748 eelf64_aix.c \
4749 eelf64_ia64.c \
4750 eelf64_ia64_fbsd.c \
4751@@ -906,6 +908,8 @@ $(ALL_EMULATION_SOURCES) $(ALL_64_EMULATION_SOURCES): $(GEN_DEPENDS)
4752 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32ltsmipn32.Pc@am__quote@
4753 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32ltsmipn32_fbsd.Pc@am__quote@
4754 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32mipswindiss.Pc@am__quote@
4755+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64microblazeel.Pc@am__quote@
4756+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64microblaze.Pc@am__quote@
4757 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64_aix.Pc@am__quote@
4758 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64_ia64.Pc@am__quote@
4759 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64_ia64_fbsd.Pc@am__quote@
4760diff --git a/ld/Makefile.in b/ld/Makefile.in
4761index ee0c98f65b0..f4b7ee0623e 100644
4762--- a/ld/Makefile.in
4763+++ b/ld/Makefile.in
4764@@ -914,6 +914,8 @@ ALL_64_EMULATION_SOURCES = \
4765 eelf32ltsmipn32.c \
4766 eelf32ltsmipn32_fbsd.c \
4767 eelf32mipswindiss.c \
4768+ eelf64microblazeel.c \
4769+ eelf64microblaze.c \
4770 eelf64_aix.c \
4771 eelf64_ia64.c \
4772 eelf64_ia64_fbsd.c \
4773@@ -1407,6 +1409,8 @@ distclean-compile:
4774 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32xstormy16.Po@am__quote@
4775 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32xtensa.Po@am__quote@
4776 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32z80.Po@am__quote@
4777+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64microblazeel.Po@am__quote@
4778+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64microblaze.Po@am__quote@
4779 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64_aix.Po@am__quote@
4780 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64_ia64.Po@am__quote@
4781 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64_ia64_fbsd.Po@am__quote@
4782@@ -2572,6 +2576,8 @@ $(ALL_EMULATION_SOURCES) $(ALL_64_EMULATION_SOURCES): $(GEN_DEPENDS)
4783 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32ltsmipn32.Pc@am__quote@
4784 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32ltsmipn32_fbsd.Pc@am__quote@
4785 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf32mipswindiss.Pc@am__quote@
4786+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64microblazeel.Pc@am__quote@
4787+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64microblaze.Pc@am__quote@
4788 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64_aix.Pc@am__quote@
4789 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64_ia64.Pc@am__quote@
4790 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eelf64_ia64_fbsd.Pc@am__quote@
4791diff --git a/ld/configure.tgt b/ld/configure.tgt
4792index 2bae9099b6a..80ffbcf23b3 100644
4793--- a/ld/configure.tgt
4794+++ b/ld/configure.tgt
4795@@ -515,6 +515,9 @@ microblaze*-linux*) targ_emul="elf32mb_linux"
4796 microblazeel*) targ_emul=elf32microblazeel
4797 targ_extra_emuls=elf32microblaze
4798 ;;
4799+microblazeel64*) targ_emul=elf64microblazeel
4800+ targ_extra_emuls=elf64microblaze
4801+ ;;
4802 microblaze*) targ_emul=elf32microblaze
4803 targ_extra_emuls=elf32microblazeel
4804 ;;
4805diff --git a/ld/emulparams/elf64microblaze.sh b/ld/emulparams/elf64microblaze.sh
4806new file mode 100644
4807index 00000000000..9c7b0eb7080
4808--- /dev/null
4809+++ b/ld/emulparams/elf64microblaze.sh
4810@@ -0,0 +1,23 @@
4811+SCRIPT_NAME=elfmicroblaze
4812+OUTPUT_FORMAT="elf64-microblazeel"
4813+#BIG_OUTPUT_FORMAT="elf64-microblaze"
4814+LITTLE_OUTPUT_FORMAT="elf64-microblazeel"
4815+#TEXT_START_ADDR=0
4816+NONPAGED_TEXT_START_ADDR=0x28
4817+ALIGNMENT=4
4818+MAXPAGESIZE=4
4819+ARCH=microblaze
4820+EMBEDDED=yes
4821+
4822+NOP=0x80000000
4823+
4824+# Hmmm, there's got to be a better way. This sets the stack to the
4825+# top of the simulator memory (2^19 bytes).
4826+#PAGE_SIZE=0x1000
4827+#DATA_ADDR=0x10000
4828+#OTHER_RELOCATING_SECTIONS='.stack 0x7000 : { _stack = .; *(.stack) }'
4829+#$@{RELOCATING+ PROVIDE (__stack = 0x7000);@}
4830+#OTHER_RELOCATING_SECTIONS='PROVIDE (_stack = _end + 0x1000);'
4831+
4832+TEMPLATE_NAME=elf32
4833+#GENERATE_SHLIB_SCRIPT=yes
4834diff --git a/ld/emulparams/elf64microblazeel.sh b/ld/emulparams/elf64microblazeel.sh
4835new file mode 100644
4836index 00000000000..9c7b0eb7080
4837--- /dev/null
4838+++ b/ld/emulparams/elf64microblazeel.sh
4839@@ -0,0 +1,23 @@
4840+SCRIPT_NAME=elfmicroblaze
4841+OUTPUT_FORMAT="elf64-microblazeel"
4842+#BIG_OUTPUT_FORMAT="elf64-microblaze"
4843+LITTLE_OUTPUT_FORMAT="elf64-microblazeel"
4844+#TEXT_START_ADDR=0
4845+NONPAGED_TEXT_START_ADDR=0x28
4846+ALIGNMENT=4
4847+MAXPAGESIZE=4
4848+ARCH=microblaze
4849+EMBEDDED=yes
4850+
4851+NOP=0x80000000
4852+
4853+# Hmmm, there's got to be a better way. This sets the stack to the
4854+# top of the simulator memory (2^19 bytes).
4855+#PAGE_SIZE=0x1000
4856+#DATA_ADDR=0x10000
4857+#OTHER_RELOCATING_SECTIONS='.stack 0x7000 : { _stack = .; *(.stack) }'
4858+#$@{RELOCATING+ PROVIDE (__stack = 0x7000);@}
4859+#OTHER_RELOCATING_SECTIONS='PROVIDE (_stack = _end + 0x1000);'
4860+
4861+TEMPLATE_NAME=elf32
4862+#GENERATE_SHLIB_SCRIPT=yes
4863diff --git a/opcodes/microblaze-dis.c b/opcodes/microblaze-dis.c
4864index f57b98fc9f7..921adce04ea 100644
4865--- a/opcodes/microblaze-dis.c
4866+++ b/opcodes/microblaze-dis.c
4867@@ -33,6 +33,7 @@
4868 #define get_field_r1(buf, instr) get_field (buf, instr, RA_MASK, RA_LOW)
4869 #define get_field_r2(buf, instr) get_field (buf, instr, RB_MASK, RB_LOW)
4870 #define get_int_field_imm(instr) ((instr & IMM_MASK) >> IMM_LOW)
4871+#define get_int_field_imml(instr) ((instr & IMML_MASK) >> IMM_LOW)
4872 #define get_int_field_r1(instr) ((instr & RA_MASK) >> RA_LOW)
4873
4874 #define NUM_STRBUFS 3
4875@@ -73,11 +74,19 @@ get_field_imm (struct string_buf *buf, long instr)
4876 }
4877
4878 static char *
4879-get_field_imm5 (struct string_buf *buf, long instr)
4880+get_field_imml (struct string_buf *buf, long instr)
4881+{
4882+ char *p = strbuf (buf);
4883+ sprintf (p, "%d", (short)((instr & IMML_MASK) >> IMM_LOW));
4884+ return p;
4885+}
4886+
4887+static char *
4888+get_field_imms (struct string_buf *buf, long instr)
4889 {
4890 char *p = strbuf (buf);
4891
4892- sprintf (p, "%d", (short)((instr & IMM5_MASK) >> IMM_LOW));
4893+ sprintf (p, "%d", (short)((instr & IMM6_MASK) >> IMM_LOW));
4894 return p;
4895 }
4896
4897@@ -91,14 +100,14 @@ get_field_imm5_mbar (struct string_buf *buf, long instr)
4898 }
4899
4900 static char *
4901-get_field_imm5width (struct string_buf *buf, long instr)
4902+get_field_immw (struct string_buf *buf, long instr)
4903 {
4904 char *p = strbuf (buf);
4905
4906 if (instr & 0x00004000)
4907- sprintf (p, "%d", (short)(((instr & IMM5_WIDTH_MASK) >> IMM_WIDTH_LOW))); /* bsefi */
4908+ sprintf (p, "%d", (short)(((instr & IMM6_WIDTH_MASK) >> IMM_WIDTH_LOW))); /* bsefi */
4909 else
4910- sprintf (p, "%d", (short)(((instr & IMM5_WIDTH_MASK) >> IMM_WIDTH_LOW) - ((instr & IMM5_MASK) >> IMM_LOW) + 1)); /* bsifi */
4911+ sprintf (p, "%d", (short)(((instr & IMM6_WIDTH_MASK) >> IMM_WIDTH_LOW) - ((instr & IMM6_MASK) >> IMM_LOW) + 1)); /* bsifi */
4912 return p;
4913 }
4914
4915@@ -308,9 +317,14 @@ print_insn_microblaze (bfd_vma memaddr, struct disassemble_info * info)
4916 }
4917 }
4918 break;
4919- case INST_TYPE_RD_R1_IMM5:
4920+ case INST_TYPE_RD_R1_IMML:
4921 print_func (stream, "\t%s, %s, %s", get_field_rd (&buf, inst),
4922- get_field_r1 (&buf, inst), get_field_imm5 (&buf, inst));
4923+ get_field_r1 (&buf, inst), get_field_imm (&buf, inst));
4924+ /* TODO: Also print symbol */
4925+ break;
4926+ case INST_TYPE_RD_R1_IMMS:
4927+ print_func (stream, "\t%s, %s, %s", get_field_rd (&buf, inst),
4928+ get_field_r1(&buf, inst), get_field_imms (&buf, inst));
4929 break;
4930 case INST_TYPE_RD_RFSL:
4931 print_func (stream, "\t%s, %s", get_field_rd (&buf, inst),
4932@@ -417,6 +431,10 @@ print_insn_microblaze (bfd_vma memaddr, struct disassemble_info * info)
4933 case INST_TYPE_RD_R2:
4934 print_func (stream, "\t%s, %s", get_field_rd (&buf, inst),
4935 get_field_r2 (&buf, inst));
4936+ break;
4937+ case INST_TYPE_IMML:
4938+ print_func (stream, "\t%s", get_field_imml (&buf, inst));
4939+ /* TODO: Also print symbol */
4940 break;
4941 case INST_TYPE_R2:
4942 print_func (stream, "\t%s", get_field_r2 (&buf, inst));
4943@@ -440,8 +458,8 @@ print_insn_microblaze (bfd_vma memaddr, struct disassemble_info * info)
4944 case INST_TYPE_NONE:
4945 break;
4946 /* For bit field insns. */
4947- case INST_TYPE_RD_R1_IMM5_IMM5:
4948- print_func (stream, "\t%s, %s, %s, %s", get_field_rd (&buf, inst),get_field_r1(&buf, inst),get_field_imm5width (&buf, inst), get_field_imm5 (&buf, inst));
4949+ case INST_TYPE_RD_R1_IMMW_IMMS:
4950+ print_func (stream, "\t%s, %s, %s, %s", get_field_rd (&buf, inst),get_field_r1(&buf, inst),get_field_immw (&buf, inst), get_field_imms (&buf, inst));
4951 break;
4952 /* For tuqula instruction */
4953 case INST_TYPE_RD:
4954diff --git a/opcodes/microblaze-opc.h b/opcodes/microblaze-opc.h
4955index 825c639a41e..ab90240d88a 100644
4956--- a/opcodes/microblaze-opc.h
4957+++ b/opcodes/microblaze-opc.h
4958@@ -40,7 +40,7 @@
4959 #define INST_TYPE_RD_SPECIAL 11
4960 #define INST_TYPE_R1 12
4961 /* New instn type for barrel shift imms. */
4962-#define INST_TYPE_RD_R1_IMM5 13
4963+#define INST_TYPE_RD_R1_IMMS 13
4964 #define INST_TYPE_RD_RFSL 14
4965 #define INST_TYPE_R1_RFSL 15
4966
4967@@ -60,7 +60,13 @@
4968 #define INST_TYPE_IMM5 20
4969
4970 /* For bsefi and bsifi */
4971-#define INST_TYPE_RD_R1_IMM5_IMM5 21
4972+#define INST_TYPE_RD_R1_IMMW_IMMS 21
4973+
4974+/* For 64-bit instructions */
4975+#define INST_TYPE_IMML 22
4976+#define INST_TYPE_RD_R1_IMML 23
4977+#define INST_TYPE_R1_IMML 24
4978+#define INST_TYPE_RD_R1_IMMW_IMMS 21
4979
4980 #define INST_TYPE_NONE 25
4981
4982@@ -91,13 +97,14 @@
4983 #define OPCODE_MASK_H24 0xFC1F07FF /* High 6, bits 20-16 and low 11 bits. */
4984 #define OPCODE_MASK_H124 0xFFFF07FF /* High 16, and low 11 bits. */
4985 #define OPCODE_MASK_H1234 0xFFFFFFFF /* All 32 bits. */
4986-#define OPCODE_MASK_H3 0xFC000600 /* High 6 bits and bits 21, 22. */
4987-#define OPCODE_MASK_H3B 0xFC00C600 /* High 6 bits and bits 16, 17, 21, 22. */
4988+#define OPCODE_MASK_H3 0xFC000700 /* High 6 bits and bits 21, 22, 23. */
4989+#define OPCODE_MASK_H3B 0xFC00E600 /* High 6 bits and bits 16, 17, 18, 21, 22. */
4990 #define OPCODE_MASK_H32 0xFC00FC00 /* High 6 bits and bit 16-21. */
4991-#define OPCODE_MASK_H32B 0xFC00C000 /* High 6 bits and bit 16, 17. */
4992+#define OPCODE_MASK_H32B 0xFC00E000 /* High 6 bits and bit 16, 17, 18. */
4993 #define OPCODE_MASK_H34B 0xFC0000FF /* High 6 bits and low 8 bits. */
4994 #define OPCODE_MASK_H35B 0xFC0004FF /* High 6 bits and low 9 bits. */
4995 #define OPCODE_MASK_H34C 0xFC0007E0 /* High 6 bits and bits 21-26. */
4996+#define OPCODE_MASK_H8 0xFF000000 /* High 8 bits only. */
4997
4998 /* New Mask for msrset, msrclr insns. */
4999 #define OPCODE_MASK_H23N 0xFC1F8000 /* High 6 and bits 11 - 16. */
5000@@ -107,7 +114,7 @@
5001 #define DELAY_SLOT 1
5002 #define NO_DELAY_SLOT 0
5003
5004-#define MAX_OPCODES 301
5005+#define MAX_OPCODES 412
5006
5007 const struct op_code_struct
5008 {
5009@@ -125,6 +132,7 @@ const struct op_code_struct
5010 /* More info about output format here. */
5011 } microblaze_opcodes[MAX_OPCODES] =
5012 {
5013+ /* 32-bit instructions */
5014 {"add", INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x00000000, OPCODE_MASK_H4, add, arithmetic_inst },
5015 {"rsub", INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x04000000, OPCODE_MASK_H4, rsub, arithmetic_inst },
5016 {"addc", INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x08000000, OPCODE_MASK_H4, addc, arithmetic_inst },
5017@@ -161,11 +169,11 @@ const struct op_code_struct
5018 {"ncget", INST_TYPE_RD_RFSL, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x6C006000, OPCODE_MASK_H32, ncget, anyware_inst },
5019 {"ncput", INST_TYPE_R1_RFSL, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x6C00E000, OPCODE_MASK_H32, ncput, anyware_inst },
5020 {"muli", INST_TYPE_RD_R1_IMM, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x60000000, OPCODE_MASK_H, muli, mult_inst },
5021- {"bslli", INST_TYPE_RD_R1_IMM5, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x64000400, OPCODE_MASK_H3, bslli, barrel_shift_inst },
5022- {"bsrai", INST_TYPE_RD_R1_IMM5, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x64000200, OPCODE_MASK_H3, bsrai, barrel_shift_inst },
5023- {"bsrli", INST_TYPE_RD_R1_IMM5, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x64000000, OPCODE_MASK_H3, bsrli, barrel_shift_inst },
5024- {"bsefi", INST_TYPE_RD_R1_IMM5_IMM5, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x64004000, OPCODE_MASK_H32B, bsefi, barrel_shift_inst },
5025- {"bsifi", INST_TYPE_RD_R1_IMM5_IMM5, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x64008000, OPCODE_MASK_H32B, bsifi, barrel_shift_inst },
5026+ {"bslli", INST_TYPE_RD_R1_IMMS, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x64000400, OPCODE_MASK_H3B, bslli, barrel_shift_inst },
5027+ {"bsrai", INST_TYPE_RD_R1_IMMS, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x64000200, OPCODE_MASK_H3B, bsrai, barrel_shift_inst },
5028+ {"bsrli", INST_TYPE_RD_R1_IMMS, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x64000000, OPCODE_MASK_H3B, bsrli, barrel_shift_inst },
5029+ {"bsefi", INST_TYPE_RD_R1_IMMW_IMMS, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x64004000, OPCODE_MASK_H32B, bsefi, barrel_shift_inst },
5030+ {"bsifi", INST_TYPE_RD_R1_IMMW_IMMS, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x64008000, OPCODE_MASK_H32B, bsifi, barrel_shift_inst },
5031 {"or", INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x80000000, OPCODE_MASK_H4, microblaze_or, logical_inst },
5032 {"and", INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x84000000, OPCODE_MASK_H4, microblaze_and, logical_inst },
5033 {"xor", INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x88000000, OPCODE_MASK_H4, microblaze_xor, logical_inst },
5034@@ -425,6 +433,129 @@ const struct op_code_struct
5035 {"suspend", INST_TYPE_NONE, INST_PC_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xBB020004, OPCODE_MASK_HN, invalid_inst, special_inst }, /* translates to mbar 24. */
5036 {"swapb", INST_TYPE_RD_R1, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x900001E0, OPCODE_MASK_H4, swapb, arithmetic_inst },
5037 {"swaph", INST_TYPE_RD_R1, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x900001E2, OPCODE_MASK_H4, swaph, arithmetic_inst },
5038+
5039+ /* 64-bit instructions */
5040+ {"addl", INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x00000100, OPCODE_MASK_H4, addl, arithmetic_inst },
5041+ {"rsubl", INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x04000100, OPCODE_MASK_H4, rsubl, arithmetic_inst },
5042+ {"addlc", INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x08000100, OPCODE_MASK_H4, addlc, arithmetic_inst },
5043+ {"rsublc", INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x0C000100, OPCODE_MASK_H4, rsublc, arithmetic_inst },
5044+ {"addlk", INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x10000100, OPCODE_MASK_H4, addlk, arithmetic_inst },
5045+ {"rsublk", INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x14000100, OPCODE_MASK_H4, rsublk, arithmetic_inst },
5046+ {"addlkc", INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x18000100, OPCODE_MASK_H4, addlkc, arithmetic_inst },
5047+ {"rsublkc", INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x1C000100, OPCODE_MASK_H4, rsublkc, arithmetic_inst },
5048+ {"cmpl", INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x14000101, OPCODE_MASK_H4, cmpl, arithmetic_inst },
5049+ {"cmplu", INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x14000103, OPCODE_MASK_H4, cmplu, arithmetic_inst },
5050+ {"addli", INST_TYPE_RD_R1_IMML, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x20000000, OPCODE_MASK_H, invalid_inst, arithmetic_inst }, /* Identical to 32-bit */
5051+ {"rsubli", INST_TYPE_RD_R1_IMML, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x24000000, OPCODE_MASK_H, invalid_inst, arithmetic_inst }, /* Identical to 32-bit */
5052+ {"addlic", INST_TYPE_RD_R1_IMML, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x28000000, OPCODE_MASK_H, invalid_inst, arithmetic_inst }, /* Identical to 32-bit */
5053+ {"rsublic", INST_TYPE_RD_R1_IMML, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x2C000000, OPCODE_MASK_H, invalid_inst, arithmetic_inst }, /* Identical to 32-bit */
5054+ {"addlik", INST_TYPE_RD_R1_IMML, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x30000000, OPCODE_MASK_H, invalid_inst, arithmetic_inst }, /* Identical to 32-bit */
5055+ {"rsublik", INST_TYPE_RD_R1_IMML, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x34000000, OPCODE_MASK_H, invalid_inst, arithmetic_inst }, /* Identical to 32-bit */
5056+ {"addlikc", INST_TYPE_RD_R1_IMML, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x38000000, OPCODE_MASK_H, invalid_inst, arithmetic_inst }, /* Identical to 32-bit */
5057+ {"rsublikc",INST_TYPE_RD_R1_IMML, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x3C000000, OPCODE_MASK_H, invalid_inst, arithmetic_inst }, /* Identical to 32-bit */
5058+ {"mull", INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x40000100, OPCODE_MASK_H4, mull, mult_inst },
5059+ {"bslll", INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x44000500, OPCODE_MASK_H3, bslll, barrel_shift_inst },
5060+ {"bslra", INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x44000300, OPCODE_MASK_H3, bslra, barrel_shift_inst },
5061+ {"bslrl", INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x44000100, OPCODE_MASK_H3, bslrl, barrel_shift_inst },
5062+ {"bsllli", INST_TYPE_RD_R1_IMMS, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x64002400, OPCODE_MASK_H3B, bsllli, barrel_shift_inst },
5063+ {"bslrai", INST_TYPE_RD_R1_IMMS, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x64002200, OPCODE_MASK_H3B, bslrai, barrel_shift_inst },
5064+ {"bslrli", INST_TYPE_RD_R1_IMMS, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x64002000, OPCODE_MASK_H3B, bslrli, barrel_shift_inst },
5065+ {"bslefi", INST_TYPE_RD_R1_IMMW_IMMS, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x64006000, OPCODE_MASK_H32B, bslefi, barrel_shift_inst },
5066+ {"bslifi", INST_TYPE_RD_R1_IMMW_IMMS, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x6400a000, OPCODE_MASK_H32B, bslifi, barrel_shift_inst },
5067+ {"orl", INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x80000100, OPCODE_MASK_H4, orl, logical_inst },
5068+ {"andl", INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x84000100, OPCODE_MASK_H4, andl, logical_inst },
5069+ {"xorl", INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x88000100, OPCODE_MASK_H4, xorl, logical_inst },
5070+ {"andnl", INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x8C000100, OPCODE_MASK_H4, andnl, logical_inst },
5071+ {"pcmplbf", INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x80000500, OPCODE_MASK_H4, pcmplbf, logical_inst },
5072+ {"pcmpleq", INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x88000500, OPCODE_MASK_H4, pcmpleq, logical_inst },
5073+ {"pcmplne", INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x8C000500, OPCODE_MASK_H4, pcmplne, logical_inst },
5074+ {"srla", INST_TYPE_RD_R1, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x90000101, OPCODE_MASK_H34, srla, logical_inst },
5075+ {"srlc", INST_TYPE_RD_R1, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x90000121, OPCODE_MASK_H34, srlc, logical_inst },
5076+ {"srll", INST_TYPE_RD_R1, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x90000141, OPCODE_MASK_H34, srll, logical_inst },
5077+ {"sextl8", INST_TYPE_RD_R1, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x90000160, OPCODE_MASK_H34, sextl8, logical_inst },
5078+ {"sextl16", INST_TYPE_RD_R1, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x90000161, OPCODE_MASK_H34, sextl16, logical_inst },
5079+ {"sextl32", INST_TYPE_RD_R1, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x90000162, OPCODE_MASK_H34, sextl32, logical_inst },
5080+ {"brea", INST_TYPE_R2, INST_PC_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x98010000, OPCODE_MASK_H124, brea, branch_inst },
5081+ {"bread", INST_TYPE_R2, INST_PC_OFFSET, DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x98110000, OPCODE_MASK_H124, bread, branch_inst },
5082+ {"breald", INST_TYPE_RD_R2, INST_PC_OFFSET, DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x98150000, OPCODE_MASK_H24, breald, branch_inst },
5083+ {"beaeq", INST_TYPE_R1_R2, INST_PC_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x9D000000, OPCODE_MASK_H14, beaeq, branch_inst },
5084+ {"bealeq", INST_TYPE_R1_R2, INST_PC_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x9D000100, OPCODE_MASK_H14, bealeq, branch_inst },
5085+ {"beaeqd", INST_TYPE_R1_R2, INST_PC_OFFSET, DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x9F000000, OPCODE_MASK_H14, beaeqd, branch_inst },
5086+ {"bealeqd", INST_TYPE_R1_R2, INST_PC_OFFSET, DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x9F000100, OPCODE_MASK_H14, bealeqd, branch_inst },
5087+ {"beane", INST_TYPE_R1_R2, INST_PC_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x9D200000, OPCODE_MASK_H14, beane, branch_inst },
5088+ {"bealne", INST_TYPE_R1_R2, INST_PC_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x9D200100, OPCODE_MASK_H14, bealne, branch_inst },
5089+ {"beaned", INST_TYPE_R1_R2, INST_PC_OFFSET, DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x9F200000, OPCODE_MASK_H14, beaned, branch_inst },
5090+ {"bealned", INST_TYPE_R1_R2, INST_PC_OFFSET, DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x9F200100, OPCODE_MASK_H14, bealned, branch_inst },
5091+ {"bealt", INST_TYPE_R1_R2, INST_PC_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x9D400000, OPCODE_MASK_H14, bealt, branch_inst },
5092+ {"beallt", INST_TYPE_R1_R2, INST_PC_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x9D400100, OPCODE_MASK_H14, beallt, branch_inst },
5093+ {"bealtd", INST_TYPE_R1_R2, INST_PC_OFFSET, DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x9F400000, OPCODE_MASK_H14, bealtd, branch_inst },
5094+ {"bealltd", INST_TYPE_R1_R2, INST_PC_OFFSET, DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x9F400100, OPCODE_MASK_H14, bealltd, branch_inst },
5095+ {"beale", INST_TYPE_R1_R2, INST_PC_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x9D600000, OPCODE_MASK_H14, beale, branch_inst },
5096+ {"bealle", INST_TYPE_R1_R2, INST_PC_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x9D600100, OPCODE_MASK_H14, bealle, branch_inst },
5097+ {"bealed", INST_TYPE_R1_R2, INST_PC_OFFSET, DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x9F600000, OPCODE_MASK_H14, bealed, branch_inst },
5098+ {"bealled", INST_TYPE_R1_R2, INST_PC_OFFSET, DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x9F600100, OPCODE_MASK_H14, bealled, branch_inst },
5099+ {"beagt", INST_TYPE_R1_R2, INST_PC_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x9D800000, OPCODE_MASK_H14, beagt, branch_inst },
5100+ {"bealgt", INST_TYPE_R1_R2, INST_PC_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x9D800100, OPCODE_MASK_H14, bealgt, branch_inst },
5101+ {"beagtd", INST_TYPE_R1_R2, INST_PC_OFFSET, DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x9F800000, OPCODE_MASK_H14, beagtd, branch_inst },
5102+ {"bealgtd", INST_TYPE_R1_R2, INST_PC_OFFSET, DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x9F800100, OPCODE_MASK_H14, bealgtd, branch_inst },
5103+ {"beage", INST_TYPE_R1_R2, INST_PC_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x9DA00000, OPCODE_MASK_H14, beage, branch_inst },
5104+ {"bealge", INST_TYPE_R1_R2, INST_PC_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x9DA00100, OPCODE_MASK_H14, bealge, branch_inst },
5105+ {"beaged", INST_TYPE_R1_R2, INST_PC_OFFSET, DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x9FA00000, OPCODE_MASK_H14, beaged, branch_inst },
5106+ {"bealged", INST_TYPE_R1_R2, INST_PC_OFFSET, DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x9FA00100, OPCODE_MASK_H14, bealged, branch_inst },
5107+ {"orli", INST_TYPE_RD_R1_IMML, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xA0000000, OPCODE_MASK_H, invalid_inst, logical_inst }, /* Identical to 32-bit */
5108+ {"andli", INST_TYPE_RD_R1_IMML, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xA4000000, OPCODE_MASK_H, invalid_inst, logical_inst }, /* Identical to 32-bit */
5109+ {"xorli", INST_TYPE_RD_R1_IMML, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xA8000000, OPCODE_MASK_H, invalid_inst, logical_inst }, /* Identical to 32-bit */
5110+ {"andnli", INST_TYPE_RD_R1_IMML, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xAC000000, OPCODE_MASK_H, invalid_inst, logical_inst }, /* Identical to 32-bit */
5111+ {"imml", INST_TYPE_IMML, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xB2000000, OPCODE_MASK_H8, imml, immediate_inst },
5112+ {"breai", INST_TYPE_IMM, INST_PC_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xB8010000, OPCODE_MASK_H12, breai, branch_inst },
5113+ {"breaid", INST_TYPE_IMM, INST_PC_OFFSET, DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xB8110000, OPCODE_MASK_H12, breaid, branch_inst },
5114+ {"brealid", INST_TYPE_RD_IMM, INST_PC_OFFSET, DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xB8150000, OPCODE_MASK_H2, brealid, branch_inst },
5115+ {"beaeqi", INST_TYPE_R1_IMM, INST_PC_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xBD000000, OPCODE_MASK_H1, beaeqi, branch_inst },
5116+ {"bealeqi", INST_TYPE_R1_IMML, INST_PC_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xBD000000, OPCODE_MASK_H1, invalid_inst, branch_inst }, /* Identical to beaeqi */
5117+ {"beaeqid", INST_TYPE_R1_IMM, INST_PC_OFFSET, DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xBF000000, OPCODE_MASK_H1, beaeqid, branch_inst },
5118+ {"bealeqid",INST_TYPE_R1_IMML, INST_PC_OFFSET, DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xBF000000, OPCODE_MASK_H1, invalid_inst, branch_inst }, /* Identical to beaeqid */
5119+ {"beanei", INST_TYPE_R1_IMM, INST_PC_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xBD200000, OPCODE_MASK_H1, beanei, branch_inst },
5120+ {"bealnei", INST_TYPE_R1_IMML, INST_PC_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xBD200000, OPCODE_MASK_H1, invalid_inst, branch_inst }, /* Identical to beanei */
5121+ {"beaneid", INST_TYPE_R1_IMM, INST_PC_OFFSET, DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xBF200000, OPCODE_MASK_H1, beaneid, branch_inst },
5122+ {"bealneid",INST_TYPE_R1_IMML, INST_PC_OFFSET, DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xBF200000, OPCODE_MASK_H1, invalid_inst, branch_inst }, /* Identical to beaneid */
5123+ {"bealti", INST_TYPE_R1_IMM, INST_PC_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xBD400000, OPCODE_MASK_H1, bealti, branch_inst },
5124+ {"beallti", INST_TYPE_R1_IMML, INST_PC_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xBD400000, OPCODE_MASK_H1, invalid_inst, branch_inst }, /* Identical to bealti */
5125+ {"bealtid", INST_TYPE_R1_IMM, INST_PC_OFFSET, DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xBF400000, OPCODE_MASK_H1, bealtid, branch_inst },
5126+ {"bealltid",INST_TYPE_R1_IMML, INST_PC_OFFSET, DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xBF400000, OPCODE_MASK_H1, invalid_inst, branch_inst }, /* Identical to bealtid */
5127+ {"bealei", INST_TYPE_R1_IMM, INST_PC_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xBD600000, OPCODE_MASK_H1, bealei, branch_inst },
5128+ {"beallei", INST_TYPE_R1_IMML, INST_PC_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xBD600000, OPCODE_MASK_H1, invalid_inst, branch_inst }, /* Identical to bealei */
5129+ {"bealeid", INST_TYPE_R1_IMM, INST_PC_OFFSET, DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xBF600000, OPCODE_MASK_H1, bealeid, branch_inst },
5130+ {"bealleid",INST_TYPE_R1_IMML, INST_PC_OFFSET, DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xBF600000, OPCODE_MASK_H1, invalid_inst, branch_inst }, /* Identical to bealeid */
5131+ {"beagti", INST_TYPE_R1_IMM, INST_PC_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xBD800000, OPCODE_MASK_H1, beagti, branch_inst },
5132+ {"bealgti", INST_TYPE_R1_IMML, INST_PC_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xBD800000, OPCODE_MASK_H1, invalid_inst, branch_inst }, /* Identical to beagti */
5133+ {"beagtid", INST_TYPE_R1_IMM, INST_PC_OFFSET, DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xBF800000, OPCODE_MASK_H1, beagtid, branch_inst },
5134+ {"bealgtid",INST_TYPE_R1_IMML, INST_PC_OFFSET, DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xBF800000, OPCODE_MASK_H1, invalid_inst, branch_inst }, /* Identical to beagtid */
5135+ {"beagei", INST_TYPE_R1_IMM, INST_PC_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xBDA00000, OPCODE_MASK_H1, beagei, branch_inst },
5136+ {"bealgei", INST_TYPE_R1_IMML, INST_PC_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xBDA00000, OPCODE_MASK_H1, invalid_inst, branch_inst }, /* Identical to beagei */
5137+ {"beageid", INST_TYPE_R1_IMM, INST_PC_OFFSET, DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xBFA00000, OPCODE_MASK_H1, beageid, branch_inst },
5138+ {"bealgeid",INST_TYPE_R1_IMML, INST_PC_OFFSET, DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xBFA00000, OPCODE_MASK_H1, invalid_inst, branch_inst }, /* Identical to beageid */
5139+ {"ll", INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xC8000100, OPCODE_MASK_H4, ll, memory_load_inst },
5140+ {"llr", INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xC8000300, OPCODE_MASK_H4, llr, memory_load_inst },
5141+ {"sl", INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xD8000100, OPCODE_MASK_H4, sl, memory_store_inst },
5142+ {"slr", INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xD8000300, OPCODE_MASK_H4, slr, memory_store_inst },
5143+ {"lli", INST_TYPE_RD_R1_IMM, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xEC000000, OPCODE_MASK_H, invalid_inst, memory_load_inst }, /* Identical to 32-bit */
5144+ {"sli", INST_TYPE_RD_R1_IMM, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xFC000000, OPCODE_MASK_H, invalid_inst, memory_store_inst }, /* Identical to 32-bit */
5145+ {"lla", INST_TYPE_RD_R1_IMML, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x30000000, OPCODE_MASK_H, invalid_inst, arithmetic_inst }, /* lla translates to addlik */
5146+ {"dadd", INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x58000400, OPCODE_MASK_H4, dadd, arithmetic_inst },
5147+ {"drsub", INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x58000480, OPCODE_MASK_H4, drsub, arithmetic_inst },
5148+ {"dmul", INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x58000500, OPCODE_MASK_H4, dmul, arithmetic_inst },
5149+ {"ddiv", INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x58000580, OPCODE_MASK_H4, ddiv, arithmetic_inst },
5150+ {"dcmp.lt", INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x58000610, OPCODE_MASK_H4, dcmp_lt, arithmetic_inst },
5151+ {"dcmp.eq", INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x58000620, OPCODE_MASK_H4, dcmp_eq, arithmetic_inst },
5152+ {"dcmp.le", INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x58000630, OPCODE_MASK_H4, dcmp_le, arithmetic_inst },
5153+ {"dcmp.gt", INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x58000640, OPCODE_MASK_H4, dcmp_gt, arithmetic_inst },
5154+ {"dcmp.ne", INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x58000650, OPCODE_MASK_H4, dcmp_ne, arithmetic_inst },
5155+ {"dcmp.ge", INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x58000660, OPCODE_MASK_H4, dcmp_ge, arithmetic_inst },
5156+ {"dcmp.un", INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x58000600, OPCODE_MASK_H4, dcmp_un, arithmetic_inst },
5157+ {"dbl", INST_TYPE_RD_R1, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x58000680, OPCODE_MASK_H4, dbl, arithmetic_inst },
5158+ {"dlong", INST_TYPE_RD_R1, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x58000700, OPCODE_MASK_H4, dlong, arithmetic_inst },
5159+ {"dsqrt", INST_TYPE_RD_R1, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x58000780, OPCODE_MASK_H4, dsqrt, arithmetic_inst },
5160+
5161 {"", 0, 0, 0, 0, 0, 0, 0, 0},
5162 };
5163
5164@@ -445,8 +576,17 @@ char pvr_register_prefix[] = "rpvr";
5165 #define MIN_IMM5 ((int) 0x00000000)
5166 #define MAX_IMM5 ((int) 0x0000001f)
5167
5168+#define MIN_IMM6 ((int) 0x00000000)
5169+#define MAX_IMM6 ((int) 0x0000003f)
5170+
5171 #define MIN_IMM_WIDTH ((int) 0x00000001)
5172 #define MAX_IMM_WIDTH ((int) 0x00000020)
5173
5174+#define MIN_IMM6_WIDTH ((int) 0x00000001)
5175+#define MAX_IMM6_WIDTH ((int) 0x00000040)
5176+
5177+#define MIN_IMML ((long) 0xffffff8000000000L)
5178+#define MAX_IMML ((long) 0x0000007fffffffffL)
5179+
5180 #endif /* MICROBLAZE_OPC */
5181
5182diff --git a/opcodes/microblaze-opcm.h b/opcodes/microblaze-opcm.h
5183index aa3401610d9..b242ea73c7b 100644
5184--- a/opcodes/microblaze-opcm.h
5185+++ b/opcodes/microblaze-opcm.h
5186@@ -25,6 +25,7 @@
5187
5188 enum microblaze_instr
5189 {
5190+ /* 32-bit instructions */
5191 add, rsub, addc, rsubc, addk, rsubk, addkc, rsubkc, clz, cmp, cmpu,
5192 addi, rsubi, addic, rsubic, addik, rsubik, addikc, rsubikc, mul,
5193 mulh, mulhu, mulhsu,swapb,swaph,
5194@@ -39,8 +40,8 @@ enum microblaze_instr
5195 imm, rtsd, rtid, rtbd, rted, bri, brid, brlid, brai, braid, bralid,
5196 brki, beqi, beqid, bnei, bneid, blti, bltid, blei, bleid, bgti,
5197 bgtid, bgei, bgeid, lbu, lbuea, lbur, lhu, lhuea, lhur, lw, lwea, lwr, lwx,
5198- sb, sbea, sbr, sh, shea, shr, sw, swea, swr, swx, lbui, lhui, lwi,
5199- sbi, shi, swi, msrset, msrclr, tuqula, mbi_fadd, frsub, mbi_fmul, mbi_fdiv,
5200+ sb, sbea, sbr, sh, shea, shr, sw, swea, swr, swx, lbui, lhui, lwi, lli,
5201+ sbi, shi, swi, sli, msrset, msrclr, tuqula, mbi_fadd, frsub, mbi_fmul, mbi_fdiv,
5202 fcmp_lt, fcmp_eq, fcmp_le, fcmp_gt, fcmp_ne, fcmp_ge, fcmp_un, flt,
5203 /* 'fsqrt' is a glibc:math.h symbol. */
5204 fint, microblaze_fsqrt,
5205@@ -59,6 +60,18 @@ enum microblaze_instr
5206 aputd, taputd, caputd, tcaputd, naputd, tnaputd, ncaputd, tncaputd,
5207 eagetd, teagetd, ecagetd, tecagetd, neagetd, tneagetd, necagetd, tnecagetd,
5208 eaputd, teaputd, ecaputd, tecaputd, neaputd, tneaputd, necaputd, tnecaputd,
5209+
5210+ /* 64-bit instructions */
5211+ addl, rsubl, addlc, rsublc, addlk, rsublk, addlkc, rsublkc, cmpl, cmplu, mull,
5212+ bslll, bslra, bslrl, bsllli, bslrai, bslrli, bslefi, bslifi, orl, andl, xorl,
5213+ andnl, pcmplbf, pcmpleq, pcmplne, srla, srlc, srll, sextl8, sextl16, sextl32,
5214+ brea, bread, breald, beaeq, bealeq, beaeqd, bealeqd, beane, bealne, beaned,
5215+ bealned, bealt, beallt, bealtd, bealltd, beale, bealle, bealed, bealled, beagt,
5216+ bealgt, beagtd, bealgtd, beage, bealge, beaged, bealged, breai, breaid, brealid,
5217+ beaeqi, beaeqid, beanei, beaneid, bealti, bealtid, bealei, bealeid, beagti,
5218+ beagtid, beagei, beageid, imml, ll, llr, sl, slr,
5219+ dadd, drsub, dmul, ddiv, dcmp_lt, dcmp_eq, dcmp_le, dcmp_gt, dcmp_ne, dcmp_ge,
5220+ dcmp_un, dbl, dlong, dsqrt,
5221 invalid_inst
5222 };
5223
5224@@ -136,15 +149,18 @@ enum microblaze_instr_type
5225 #define RA_MASK 0x001F0000
5226 #define RB_MASK 0x0000F800
5227 #define IMM_MASK 0x0000FFFF
5228+#define IMML_MASK 0x00FFFFFF
5229
5230-/* Imm mask for barrel shifts. */
5231+/* Imm masks for barrel shifts. */
5232 #define IMM5_MASK 0x0000001F
5233+#define IMM6_MASK 0x0000003F
5234
5235 /* Imm mask for mbar. */
5236 #define IMM5_MBAR_MASK 0x03E00000
5237
5238-/* Imm mask for extract/insert width. */
5239+/* Imm masks for extract/insert width. */
5240 #define IMM5_WIDTH_MASK 0x000007C0
5241+#define IMM6_WIDTH_MASK 0x00000FC0
5242
5243 /* FSL imm mask for get, put instructions. */
5244 #define RFSL_MASK 0x000000F
5245--
52462.37.1 (Apple Git-137.1)
5247