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