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