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