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