blob: 406d7bf2cd8e3c7971ee3b4ba3e521a6b79b0f99 [file] [log] [blame]
Brad Bishop26bdd442019-08-16 17:08:17 -04001From 549bf1fafb7dfa2718e172a94ff68acb14320ed8 Mon Sep 17 00:00:00 2001
2From: Nagaraju Mekala <nmekala@xilix.com>
3Date: Sun, 30 Sep 2018 16:31:26 +0530
4Subject: [PATCH] MB-X initial commit code cleanup is needed.
5
6Signed-off-by: Mahesh Bodapati <mbodapat@xilinx.com>
7Signed-off-by: Nagaraju Mekala <nagaraju.mekala@xilinx.com>
8
9---
10 bfd/bfd-in2.h | 10 +++
11 bfd/elf32-microblaze.c | 65 +++++++++++++++++--
12 bfd/elf64-microblaze.c | 61 +++++++++++++++++-
13 bfd/libbfd.h | 2 +
14 bfd/reloc.c | 12 ++++
15 gas/config/tc-microblaze.c | 152 +++++++++++++++++++++++++++++++++++++--------
16 include/elf/microblaze.h | 2 +
17 opcodes/microblaze-opc.h | 4 +-
18 opcodes/microblaze-opcm.h | 4 +-
19 9 files changed, 277 insertions(+), 35 deletions(-)
20
21diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
22index fe6933a..90645d1 100644
23--- a/bfd/bfd-in2.h
24+++ b/bfd/bfd-in2.h
25@@ -5878,11 +5878,21 @@ done here - only used for relaxing */
26 BFD_RELOC_MICROBLAZE_64_NONE,
27
28 /* This is a 64 bit reloc that stores the 32 bit pc relative
29+ * +value in two words (with an imml instruction). No relocation is
30+ * +done here - only used for relaxing */
31+ BFD_RELOC_MICROBLAZE_64,
32+
33+/* This is a 64 bit reloc that stores the 32 bit pc relative
34 value in two words (with an imm instruction). The relocation is
35 PC-relative GOT offset */
36 BFD_RELOC_MICROBLAZE_64_GOTPC,
37
38 /* This is a 64 bit reloc that stores the 32 bit pc relative
39+value in two words (with an imml instruction). The relocation is
40+PC-relative GOT offset */
41+ BFD_RELOC_MICROBLAZE_64_GPC,
42+
43+/* This is a 64 bit reloc that stores the 32 bit pc relative
44 value in two words (with an imm instruction). The relocation is
45 GOT offset */
46 BFD_RELOC_MICROBLAZE_64_GOT,
47diff --git a/bfd/elf32-microblaze.c b/bfd/elf32-microblaze.c
48index d001437..035e71f 100644
49--- a/bfd/elf32-microblaze.c
50+++ b/bfd/elf32-microblaze.c
51@@ -116,6 +116,20 @@ static reloc_howto_type microblaze_elf_howto_raw[] =
52 0x0000ffff, /* Dest Mask. */
53 TRUE), /* PC relative offset? */
54
55+ HOWTO (R_MICROBLAZE_IMML_64, /* Type. */
56+ 0, /* Rightshift. */
57+ 2, /* Size (0 = byte, 1 = short, 2 = long). */
58+ 16, /* Bitsize. */
59+ TRUE, /* PC_relative. */
60+ 0, /* Bitpos. */
61+ complain_overflow_dont, /* Complain on overflow. */
62+ bfd_elf_generic_reloc,/* Special Function. */
63+ "R_MICROBLAZE_IMML_64", /* Name. */
64+ FALSE, /* Partial Inplace. */
65+ 0, /* Source Mask. */
66+ 0x0000ffff, /* Dest Mask. */
67+ FALSE), /* PC relative offset? */
68+
69 /* A 64 bit relocation. Table entry not really used. */
70 HOWTO (R_MICROBLAZE_64, /* Type. */
71 0, /* Rightshift. */
72@@ -280,6 +294,21 @@ static reloc_howto_type microblaze_elf_howto_raw[] =
73 0x0000ffff, /* Dest Mask. */
74 TRUE), /* PC relative offset? */
75
76+ /* A 64 bit GOTPC relocation. Table-entry not really used. */
77+ HOWTO (R_MICROBLAZE_GPC_64, /* Type. */
78+ 0, /* Rightshift. */
79+ 2, /* Size (0 = byte, 1 = short, 2 = long). */
80+ 16, /* Bitsize. */
81+ TRUE, /* PC_relative. */
82+ 0, /* Bitpos. */
83+ complain_overflow_dont, /* Complain on overflow. */
84+ bfd_elf_generic_reloc, /* Special Function. */
85+ "R_MICROBLAZE_GPC_64", /* Name. */
86+ FALSE, /* Partial Inplace. */
87+ 0, /* Source Mask. */
88+ 0x0000ffff, /* Dest Mask. */
89+ TRUE), /* PC relative offset? */
90+
91 /* A 64 bit GOT relocation. Table-entry not really used. */
92 HOWTO (R_MICROBLAZE_GOT_64, /* Type. */
93 0, /* Rightshift. */
94@@ -619,9 +648,15 @@ microblaze_elf_reloc_type_lookup (bfd * abfd ATTRIBUTE_UNUSED,
95 case BFD_RELOC_VTABLE_ENTRY:
96 microblaze_reloc = R_MICROBLAZE_GNU_VTENTRY;
97 break;
98+ case BFD_RELOC_MICROBLAZE_64:
99+ microblaze_reloc = R_MICROBLAZE_IMML_64;
100+ break;
101 case BFD_RELOC_MICROBLAZE_64_GOTPC:
102 microblaze_reloc = R_MICROBLAZE_GOTPC_64;
103 break;
104+ case BFD_RELOC_MICROBLAZE_64_GPC:
105+ microblaze_reloc = R_MICROBLAZE_GPC_64;
106+ break;
107 case BFD_RELOC_MICROBLAZE_64_GOT:
108 microblaze_reloc = R_MICROBLAZE_GOT_64;
109 break;
110@@ -1467,7 +1502,7 @@ microblaze_elf_relocate_section (bfd *output_bfd,
111 if (r_symndx == STN_UNDEF || (input_section->flags & SEC_ALLOC) == 0)
112 {
113 relocation += addend;
114- if (r_type == R_MICROBLAZE_32)
115+ if (r_type == R_MICROBLAZE_32)// || r_type == R_MICROBLAZE_IMML_64)
116 bfd_put_32 (input_bfd, relocation, contents + offset);
117 else
118 {
119@@ -1933,6 +1968,28 @@ microblaze_elf_relax_section (bfd *abfd,
120 irel->r_addend -= calc_fixup (irel->r_addend, 0, sec);
121 }
122 break;
123+ case R_MICROBLAZE_IMML_64:
124+ {
125+ /* This was a PC-relative instruction that was
126+ completely resolved. */
127+ int sfix, efix;
128+ unsigned int val;
129+ bfd_vma target_address;
130+ target_address = irel->r_addend + irel->r_offset;
131+ sfix = calc_fixup (irel->r_offset, 0, sec);
132+ efix = calc_fixup (target_address, 0, sec);
133+
134+ /* Validate the in-band val. */
135+ val = bfd_get_32 (abfd, contents + irel->r_offset);
136+ if (val != irel->r_addend && ELF64_R_TYPE (irel->r_info) == R_MICROBLAZE_32_NONE) {
137+ fprintf(stderr, "%d: CORRUPT relax reloc %x %lx\n", __LINE__, val, irel->r_addend);
138+ }
139+ irel->r_addend -= (efix - sfix);
140+ /* Should use HOWTO. */
141+ microblaze_bfd_write_imm_value_64 (abfd, contents + irel->r_offset,
142+ irel->r_addend);
143+ }
144+ break;
145 case R_MICROBLAZE_NONE:
146 case R_MICROBLAZE_32_NONE:
147 {
148@@ -2037,9 +2094,9 @@ microblaze_elf_relax_section (bfd *abfd,
149 microblaze_bfd_write_imm_value_32 (abfd, ocontents + irelscan->r_offset,
150 irelscan->r_addend);
151 }
152- if (ELF32_R_TYPE (irelscan->r_info) == (int) R_MICROBLAZE_32)
153- {
154- isym = isymbuf + ELF32_R_SYM (irelscan->r_info);
155+ if (ELF32_R_TYPE (irelscan->r_info) == (int) R_MICROBLAZE_32)// || ELF32_R_TYPE (irelscan->r_info) == (int) R_MICROBLAZE_IMML_64)
156+ {
157+ isym = isymbuf + ELF32_R_SYM (irelscan->r_info);
158
159 /* Look at the reloc only if the value has been resolved. */
160 if (isym->st_shndx == shndx
161diff --git a/bfd/elf64-microblaze.c b/bfd/elf64-microblaze.c
162index 0f43ae6..56a45f2 100644
163--- a/bfd/elf64-microblaze.c
164+++ b/bfd/elf64-microblaze.c
165@@ -117,6 +117,21 @@ static reloc_howto_type microblaze_elf_howto_raw[] =
166 TRUE), /* PC relative offset? */
167
168 /* A 64 bit relocation. Table entry not really used. */
169+ HOWTO (R_MICROBLAZE_IMML_64, /* Type. */
170+ 0, /* Rightshift. */
171+ 4, /* Size (0 = byte, 1 = short, 2 = long). */
172+ 64, /* Bitsize. */
173+ TRUE, /* PC_relative. */
174+ 0, /* Bitpos. */
175+ complain_overflow_dont, /* Complain on overflow. */
176+ bfd_elf_generic_reloc,/* Special Function. */
177+ "R_MICROBLAZE_IMML_64", /* Name. */
178+ FALSE, /* Partial Inplace. */
179+ 0, /* Source Mask. */
180+ 0x0000ffff, /* Dest Mask. */
181+ TRUE), /* PC relative offset? */
182+
183+ /* A 64 bit relocation. Table entry not really used. */
184 HOWTO (R_MICROBLAZE_64, /* Type. */
185 0, /* Rightshift. */
186 2, /* Size (0 = byte, 1 = short, 2 = long). */
187@@ -265,6 +280,21 @@ static reloc_howto_type microblaze_elf_howto_raw[] =
188 0x0000ffff, /* Dest Mask. */
189 TRUE), /* PC relative offset? */
190
191+ /* A 64 bit GOTPC relocation. Table-entry not really used. */
192+ HOWTO (R_MICROBLAZE_GPC_64, /* Type. */
193+ 0, /* Rightshift. */
194+ 2, /* Size (0 = byte, 1 = short, 2 = long). */
195+ 16, /* Bitsize. */
196+ TRUE, /* PC_relative. */
197+ 0, /* Bitpos. */
198+ complain_overflow_dont, /* Complain on overflow. */
199+ bfd_elf_generic_reloc, /* Special Function. */
200+ "R_MICROBLAZE_GPC_64", /* Name. */
201+ FALSE, /* Partial Inplace. */
202+ 0, /* Source Mask. */
203+ 0x0000ffff, /* Dest Mask. */
204+ TRUE), /* PC relative offset? */
205+
206 /* A 64 bit GOT relocation. Table-entry not really used. */
207 HOWTO (R_MICROBLAZE_GOT_64, /* Type. */
208 0, /* Rightshift. */
209@@ -589,9 +619,15 @@ microblaze_elf_reloc_type_lookup (bfd * abfd ATTRIBUTE_UNUSED,
210 case BFD_RELOC_VTABLE_ENTRY:
211 microblaze_reloc = R_MICROBLAZE_GNU_VTENTRY;
212 break;
213+ case BFD_RELOC_MICROBLAZE_64:
214+ microblaze_reloc = R_MICROBLAZE_IMML_64;
215+ break;
216 case BFD_RELOC_MICROBLAZE_64_GOTPC:
217 microblaze_reloc = R_MICROBLAZE_GOTPC_64;
218 break;
219+ case BFD_RELOC_MICROBLAZE_64_GPC:
220+ microblaze_reloc = R_MICROBLAZE_GPC_64;
221+ break;
222 case BFD_RELOC_MICROBLAZE_64_GOT:
223 microblaze_reloc = R_MICROBLAZE_GOT_64;
224 break;
225@@ -1161,6 +1197,7 @@ microblaze_elf_relocate_section (bfd *output_bfd,
226 break; /* Do nothing. */
227
228 case (int) R_MICROBLAZE_GOTPC_64:
229+ case (int) R_MICROBLAZE_GPC_64:
230 relocation = htab->sgotplt->output_section->vma
231 + htab->sgotplt->output_offset;
232 relocation -= (input_section->output_section->vma
233@@ -1431,7 +1468,7 @@ microblaze_elf_relocate_section (bfd *output_bfd,
234 if (r_symndx == STN_UNDEF || (input_section->flags & SEC_ALLOC) == 0)
235 {
236 relocation += addend;
237- if (r_type == R_MICROBLAZE_32)
238+ if (r_type == R_MICROBLAZE_32)// || r_type == R_MICROBLAZE_IMML_64)
239 bfd_put_32 (input_bfd, relocation, contents + offset);
240 else
241 {
242@@ -1876,6 +1913,28 @@ microblaze_elf_relax_section (bfd *abfd,
243 irel->r_addend -= calc_fixup (irel->r_addend, 0, sec);
244 }
245 break;
246+ case R_MICROBLAZE_IMML_64:
247+ {
248+ /* This was a PC-relative instruction that was
249+ completely resolved. */
250+ int sfix, efix;
251+ unsigned int val;
252+ bfd_vma target_address;
253+ target_address = irel->r_addend + irel->r_offset;
254+ sfix = calc_fixup (irel->r_offset, 0, sec);
255+ efix = calc_fixup (target_address, 0, sec);
256+
257+ /* Validate the in-band val. */
258+ val = bfd_get_32 (abfd, contents + irel->r_offset);
259+ if (val != irel->r_addend && ELF64_R_TYPE (irel->r_info) == R_MICROBLAZE_32_NONE) {
260+ fprintf(stderr, "%d: CORRUPT relax reloc %x %lx\n", __LINE__, val, irel->r_addend);
261+ }
262+ irel->r_addend -= (efix - sfix);
263+ /* Should use HOWTO. */
264+ microblaze_bfd_write_imm_value_64 (abfd, contents + irel->r_offset,
265+ irel->r_addend);
266+ }
267+ break;
268 case R_MICROBLAZE_NONE:
269 case R_MICROBLAZE_32_NONE:
270 {
271diff --git a/bfd/libbfd.h b/bfd/libbfd.h
272index feb9fad..450653f 100644
273--- a/bfd/libbfd.h
274+++ b/bfd/libbfd.h
275@@ -2903,7 +2903,9 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@",
276 "BFD_RELOC_MICROBLAZE_32_SYM_OP_SYM",
277 "BFD_RELOC_MICROBLAZE_32_NONE",
278 "BFD_RELOC_MICROBLAZE_64_NONE",
279+ "BFD_RELOC_MICROBLAZE_64",
280 "BFD_RELOC_MICROBLAZE_64_GOTPC",
281+ "BFD_RELOC_MICROBLAZE_64_GPC",
282 "BFD_RELOC_MICROBLAZE_64_GOT",
283 "BFD_RELOC_MICROBLAZE_64_PLT",
284 "BFD_RELOC_MICROBLAZE_64_GOTOFF",
285diff --git a/bfd/reloc.c b/bfd/reloc.c
286index 87753ae..ccf29f5 100644
287--- a/bfd/reloc.c
288+++ b/bfd/reloc.c
289@@ -6804,6 +6804,12 @@ ENUMDOC
290 ENUM
291 BFD_RELOC_MICROBLAZE_64_NONE
292 ENUMDOC
293+ This is a 32 bit reloc that stores the 32 bit pc relative
294+ value in two words (with an imml instruction). No relocation is
295+ done here - only used for relaxing
296+ENUM
297+ BFD_RELOC_MICROBLAZE_64
298+ENUMDOC
299 This is a 64 bit reloc that stores the 32 bit pc relative
300 value in two words (with an imm instruction). No relocation is
301 done here - only used for relaxing
302@@ -6811,6 +6817,12 @@ ENUM
303 BFD_RELOC_MICROBLAZE_64_GOTPC
304 ENUMDOC
305 This is a 64 bit reloc that stores the 32 bit pc relative
306+ value in two words (with an imml instruction). No relocation is
307+ done here - only used for relaxing
308+ENUM
309+ BFD_RELOC_MICROBLAZE_64_GPC
310+ENUMDOC
311+ This is a 64 bit reloc that stores the 32 bit pc relative
312 value in two words (with an imm instruction). The relocation is
313 PC-relative GOT offset
314 ENUM
315diff --git a/gas/config/tc-microblaze.c b/gas/config/tc-microblaze.c
316index c794347..3f90b7c 100644
317--- a/gas/config/tc-microblaze.c
318+++ b/gas/config/tc-microblaze.c
319@@ -94,6 +94,7 @@ const char FLT_CHARS[] = "rRsSfFdDxXpP";
320 #define TLSTPREL_OFFSET 16
321 #define TEXT_OFFSET 17
322 #define TEXT_PC_OFFSET 18
323+#define DEFINED_64_OFFSET 19
324
325 /* Initialize the relax table. */
326 const relax_typeS md_relax_table[] =
327@@ -117,6 +118,8 @@ const relax_typeS md_relax_table[] =
328 { 0x7fffffff, 0x80000000, INST_WORD_SIZE*2, 0 }, /* 16: TLSTPREL_OFFSET. */
329 { 0x7fffffff, 0x80000000, INST_WORD_SIZE*2, 0 }, /* 17: TEXT_OFFSET. */
330 { 0x7fffffff, 0x80000000, INST_WORD_SIZE*2, 0 } /* 18: TEXT_PC_OFFSET. */
331+// { 0x7fffffff, 0x80000000, INST_WORD_SIZE*2, 0 } /* 16: TLSTPREL_OFFSET. */
332+ { 0x7fffffffffffffff, 0x8000000000000000, INST_WORD_SIZE, 0 } /* 17: DEFINED_64_OFFSET. */
333 };
334
335 static struct hash_control * opcode_hash_control; /* Opcode mnemonics. */
336@@ -396,7 +399,8 @@ const pseudo_typeS md_pseudo_table[] =
337 {"data32", cons, 4}, /* Same as word. */
338 {"ent", s_func, 0}, /* Treat ent as function entry point. */
339 {"end", microblaze_s_func, 1}, /* Treat end as function end point. */
340- {"gpword", s_rva, 4}, /* gpword label => store resolved label address in data section. */
341+ {"gpword", s_rva, 8}, /* gpword label => store resolved label address in data section. */
342+ {"gpdword", s_rva, 8}, /* gpword label => store resolved label address in data section. */
343 {"weakext", microblaze_s_weakext, 0},
344 {"rodata", microblaze_s_rdata, 0},
345 {"sdata2", microblaze_s_rdata, 1},
346@@ -405,6 +409,7 @@ const pseudo_typeS md_pseudo_table[] =
347 {"sbss", microblaze_s_bss, 1},
348 {"text", microblaze_s_text, 0},
349 {"word", cons, 4},
350+ {"dword", cons, 8},
351 {"frame", s_ignore, 0},
352 {"mask", s_ignore, 0}, /* Emitted by gcc. */
353 {NULL, NULL, 0}
354@@ -898,7 +903,7 @@ check_got (int * got_type, int * got_len)
355 extern bfd_reloc_code_real_type
356 parse_cons_expression_microblaze (expressionS *exp, int size)
357 {
358- if (size == 4)
359+ if (size == 4 || (microblaze_arch_size == 64 && size == 8))
360 {
361 /* Handle @GOTOFF et.al. */
362 char *save, *gotfree_copy;
363@@ -930,6 +935,7 @@ parse_cons_expression_microblaze (expressionS *exp, int size)
364
365 static const char * str_microblaze_ro_anchor = "RO";
366 static const char * str_microblaze_rw_anchor = "RW";
367+static const char * str_microblaze_64 = "64";
368
369 static bfd_boolean
370 check_spl_reg (unsigned * reg)
371@@ -1174,6 +1180,33 @@ md_assemble (char * str)
372 inst |= (immed << IMM_LOW) & IMM_MASK;
373 }
374 }
375+#if 0 //revisit
376+ else if (streq (name, "lli") || streq (name, "sli"))
377+ {
378+ temp = immed & 0xFFFFFFFFFFFF8000;
379+ if ((temp != 0) && (temp != 0xFFFFFFFFFFFF8000))
380+ {
381+ /* Needs an immediate inst. */
382+ opcode1 = (struct op_code_struct *) hash_find (opcode_hash_control, "imml");
383+ if (opcode1 == NULL)
384+ {
385+ as_bad (_("unknown opcode \"%s\""), "imml");
386+ return;
387+ }
388+
389+ inst1 = opcode1->bit_sequence;
390+ inst1 |= ((immedl & 0xFFFFFFFFFFFF0000L) >> 16) & IMML_MASK;
391+ output[0] = INST_BYTE0 (inst1);
392+ output[1] = INST_BYTE1 (inst1);
393+ output[2] = INST_BYTE2 (inst1);
394+ output[3] = INST_BYTE3 (inst1);
395+ output = frag_more (isize);
396+ }
397+ inst |= (reg1 << RD_LOW) & RD_MASK;
398+ inst |= (reg2 << RA_LOW) & RA_MASK;
399+ inst |= (immed << IMM_LOW) & IMM_MASK;
400+ }
401+#endif
402 else
403 {
404 temp = immed & 0xFFFF8000;
405@@ -1926,6 +1959,7 @@ md_assemble (char * str)
406 if (exp.X_op != O_constant)
407 {
408 char *opc = NULL;
409+ //char *opc = str_microblaze_64;
410 relax_substateT subtype;
411
412 if (exp.X_md != 0)
413@@ -1939,7 +1973,7 @@ md_assemble (char * str)
414 subtype, /* PC-relative or not. */
415 exp.X_add_symbol,
416 exp.X_add_number,
417- opc);
418+ (char *) opc);
419 immedl = 0L;
420 }
421 else
422@@ -1977,7 +2011,7 @@ md_assemble (char * str)
423 reg1 = 0;
424 }
425 if (strcmp (op_end, ""))
426- op_end = parse_imml (op_end + 1, & exp, MIN_IMM, MAX_IMM);
427+ op_end = parse_imml (op_end + 1, & exp, MIN_IMML, MAX_IMML);
428 else
429 as_fatal (_("Error in statement syntax"));
430
431@@ -1987,7 +2021,8 @@ md_assemble (char * str)
432
433 if (exp.X_op != O_constant)
434 {
435- char *opc = NULL;
436+ //char *opc = NULL;
437+ char *opc = str_microblaze_64;
438 relax_substateT subtype;
439
440 if (exp.X_md != 0)
441@@ -2001,14 +2036,13 @@ md_assemble (char * str)
442 subtype, /* PC-relative or not. */
443 exp.X_add_symbol,
444 exp.X_add_number,
445- opc);
446+ (char *) opc);
447 immedl = 0L;
448 }
449 else
450 {
451 output = frag_more (isize);
452 immedl = exp.X_add_number;
453-
454 opcode1 = (struct op_code_struct *) hash_find (opcode_hash_control, "imml");
455 if (opcode1 == NULL)
456 {
457@@ -2187,13 +2221,23 @@ md_convert_frag (bfd * abfd ATTRIBUTE_UNUSED,
458 fragP->fr_fix += INST_WORD_SIZE * 2;
459 fragP->fr_var = 0;
460 break;
461+ case DEFINED_64_OFFSET:
462+ if (fragP->fr_symbol == GOT_symbol)
463+ fix_new (fragP, fragP->fr_fix, INST_WORD_SIZE, fragP->fr_symbol,
464+ fragP->fr_offset, TRUE, BFD_RELOC_MICROBLAZE_64_GPC);
465+ else
466+ fix_new (fragP, fragP->fr_fix, INST_WORD_SIZE, fragP->fr_symbol,
467+ fragP->fr_offset, TRUE, BFD_RELOC_MICROBLAZE_64);
468+ fragP->fr_fix += INST_WORD_SIZE * 2;
469+ fragP->fr_var = 0;
470+ break;
471 case DEFINED_ABS_SEGMENT:
472 if (fragP->fr_symbol == GOT_symbol)
473 fix_new (fragP, fragP->fr_fix, INST_WORD_SIZE * 2, fragP->fr_symbol,
474 fragP->fr_offset, TRUE, BFD_RELOC_MICROBLAZE_64_GOTPC);
475 else
476 fix_new (fragP, fragP->fr_fix, INST_WORD_SIZE * 2, fragP->fr_symbol,
477- fragP->fr_offset, FALSE, BFD_RELOC_64);
478+ fragP->fr_offset, TRUE, BFD_RELOC_64);
479 fragP->fr_fix += INST_WORD_SIZE * 2;
480 fragP->fr_var = 0;
481 break;
482@@ -2416,22 +2460,38 @@ md_apply_fix (fixS * fixP,
483 case BFD_RELOC_64_PCREL:
484 case BFD_RELOC_64:
485 case BFD_RELOC_MICROBLAZE_64_TEXTREL:
486+ case BFD_RELOC_MICROBLAZE_64:
487 /* Add an imm instruction. First save the current instruction. */
488 for (i = 0; i < INST_WORD_SIZE; i++)
489 buf[i + INST_WORD_SIZE] = buf[i];
490+ if (fixP->fx_r_type == BFD_RELOC_MICROBLAZE_64)
491+ {
492+ /* Generate the imm instruction. */
493+ opcode1 = (struct op_code_struct *) hash_find (opcode_hash_control, "imml");
494+ if (opcode1 == NULL)
495+ {
496+ as_bad (_("unknown opcode \"%s\""), "imml");
497+ return;
498+ }
499
500- /* Generate the imm instruction. */
501- opcode1 = (struct op_code_struct *) hash_find (opcode_hash_control, "imm");
502- if (opcode1 == NULL)
503- {
504- as_bad (_("unknown opcode \"%s\""), "imm");
505- return;
506- }
507-
508- inst1 = opcode1->bit_sequence;
509- if (fixP->fx_addsy == NULL || S_IS_DEFINED (fixP->fx_addsy))
510- inst1 |= ((val & 0xFFFF0000) >> 16) & IMM_MASK;
511-
512+ inst1 = opcode1->bit_sequence;
513+ if (fixP->fx_addsy == NULL || S_IS_DEFINED (fixP->fx_addsy))
514+ inst1 |= ((val & 0xFFFFFFFFFFFF0000L) >> 16) & IMML_MASK;
515+ }
516+ else
517+ {
518+ /* Generate the imm instruction. */
519+ opcode1 = (struct op_code_struct *) hash_find (opcode_hash_control, "imm");
520+ if (opcode1 == NULL)
521+ {
522+ as_bad (_("unknown opcode \"%s\""), "imm");
523+ return;
524+ }
525+
526+ inst1 = opcode1->bit_sequence;
527+ if (fixP->fx_addsy == NULL || S_IS_DEFINED (fixP->fx_addsy))
528+ inst1 |= ((val & 0xFFFF0000) >> 16) & IMM_MASK;
529+ }
530 buf[0] = INST_BYTE0 (inst1);
531 buf[1] = INST_BYTE1 (inst1);
532 buf[2] = INST_BYTE2 (inst1);
533@@ -2460,6 +2520,7 @@ md_apply_fix (fixS * fixP,
534 /* Fall through. */
535
536 case BFD_RELOC_MICROBLAZE_64_GOTPC:
537+ case BFD_RELOC_MICROBLAZE_64_GPC:
538 case BFD_RELOC_MICROBLAZE_64_GOT:
539 case BFD_RELOC_MICROBLAZE_64_PLT:
540 case BFD_RELOC_MICROBLAZE_64_GOTOFF:
541@@ -2467,12 +2528,16 @@ md_apply_fix (fixS * fixP,
542 /* Add an imm instruction. First save the current instruction. */
543 for (i = 0; i < INST_WORD_SIZE; i++)
544 buf[i + INST_WORD_SIZE] = buf[i];
545-
546- /* Generate the imm instruction. */
547- opcode1 = (struct op_code_struct *) hash_find (opcode_hash_control, "imm");
548+ if (fixP->fx_r_type == BFD_RELOC_MICROBLAZE_64_GPC)
549+ opcode1 = (struct op_code_struct *) hash_find (opcode_hash_control, "imml");
550+ else
551+ opcode1 = (struct op_code_struct *) hash_find (opcode_hash_control, "imm");
552 if (opcode1 == NULL)
553 {
554- as_bad (_("unknown opcode \"%s\""), "imm");
555+ if (fixP->fx_r_type == BFD_RELOC_MICROBLAZE_64_GPC)
556+ as_bad (_("unknown opcode \"%s\""), "imml");
557+ else
558+ as_bad (_("unknown opcode \"%s\""), "imm");
559 return;
560 }
561
562@@ -2496,6 +2561,8 @@ md_apply_fix (fixS * fixP,
563 moves code around due to relaxing. */
564 if (fixP->fx_r_type == BFD_RELOC_64_PCREL)
565 fixP->fx_r_type = BFD_RELOC_MICROBLAZE_64_NONE;
566+ if (fixP->fx_r_type == BFD_RELOC_MICROBLAZE_64)
567+ fixP->fx_r_type = BFD_RELOC_MICROBLAZE_64_NONE;
568 else if (fixP->fx_r_type == BFD_RELOC_32)
569 fixP->fx_r_type = BFD_RELOC_MICROBLAZE_32_NONE;
570 else
571@@ -2539,6 +2606,32 @@ md_estimate_size_before_relax (fragS * fragP,
572 as_bad (_("Absolute PC-relative value in relaxation code. Assembler error....."));
573 abort ();
574 }
575+ else if (S_GET_SEGMENT (fragP->fr_symbol) == segment_type
576+ && !S_IS_WEAK (fragP->fr_symbol))
577+ {
578+ if (fragP->fr_opcode != NULL) {
579+ if(streq (fragP->fr_opcode, str_microblaze_64))
580+ {
581+ /* Used as an absolute value. */
582+ fragP->fr_subtype = DEFINED_64_OFFSET;
583+ /* Variable part does not change. */
584+ fragP->fr_var = INST_WORD_SIZE;
585+ }
586+ else
587+ {
588+ fragP->fr_subtype = DEFINED_PC_OFFSET;
589+ /* Don't know now whether we need an imm instruction. */
590+ fragP->fr_var = INST_WORD_SIZE;
591+ }
592+ }
593+ else
594+ {
595+ fragP->fr_subtype = DEFINED_PC_OFFSET;
596+ /* Don't know now whether we need an imm instruction. */
597+ fragP->fr_var = INST_WORD_SIZE;
598+ }
599+ }
600+ #if 0
601 else if (S_GET_SEGMENT (fragP->fr_symbol) == segment_type &&
602 !S_IS_WEAK (fragP->fr_symbol))
603 {
604@@ -2546,6 +2639,7 @@ md_estimate_size_before_relax (fragS * fragP,
605 /* Don't know now whether we need an imm instruction. */
606 fragP->fr_var = INST_WORD_SIZE;
607 }
608+#endif
609 else if (S_IS_DEFINED (fragP->fr_symbol)
610 && (((S_GET_SEGMENT (fragP->fr_symbol))->flags & SEC_CODE) == 0))
611 {
612@@ -2648,6 +2742,7 @@ md_estimate_size_before_relax (fragS * fragP,
613 case TLSLD_OFFSET:
614 case TLSTPREL_OFFSET:
615 case TLSDTPREL_OFFSET:
616+ case DEFINED_64_OFFSET:
617 fragP->fr_var = INST_WORD_SIZE*2;
618 break;
619 case DEFINED_RO_SEGMENT:
620@@ -2701,7 +2796,7 @@ md_pcrel_from_section (fixS * fixp, segT sec ATTRIBUTE_UNUSED)
621 else
622 {
623 /* The case where we are going to resolve things... */
624- if (fixp->fx_r_type == BFD_RELOC_64_PCREL)
625+ if (fixp->fx_r_type == BFD_RELOC_64_PCREL ||fixp->fx_r_type == BFD_RELOC_MICROBLAZE_64)
626 return fixp->fx_where + fixp->fx_frag->fr_address + INST_WORD_SIZE;
627 else
628 return fixp->fx_where + fixp->fx_frag->fr_address;
629@@ -2734,6 +2829,8 @@ tc_gen_reloc (asection * section ATTRIBUTE_UNUSED, fixS * fixp)
630 case BFD_RELOC_MICROBLAZE_32_RWSDA:
631 case BFD_RELOC_MICROBLAZE_32_SYM_OP_SYM:
632 case BFD_RELOC_MICROBLAZE_64_GOTPC:
633+ case BFD_RELOC_MICROBLAZE_64_GPC:
634+ case BFD_RELOC_MICROBLAZE_64:
635 case BFD_RELOC_MICROBLAZE_64_GOT:
636 case BFD_RELOC_MICROBLAZE_64_PLT:
637 case BFD_RELOC_MICROBLAZE_64_GOTOFF:
638@@ -2876,7 +2973,10 @@ cons_fix_new_microblaze (fragS * frag,
639 r = BFD_RELOC_32;
640 break;
641 case 8:
642- r = BFD_RELOC_64;
643+ if (microblaze_arch_size == 64)
644+ r = BFD_RELOC_32;
645+ else
646+ r = BFD_RELOC_64;
647 break;
648 default:
649 as_bad (_("unsupported BFD relocation size %u"), size);
650diff --git a/include/elf/microblaze.h b/include/elf/microblaze.h
651index 6ee0966..16b2736 100644
652--- a/include/elf/microblaze.h
653+++ b/include/elf/microblaze.h
654@@ -62,6 +62,8 @@ START_RELOC_NUMBERS (elf_microblaze_reloc_type)
655 RELOC_NUMBER (R_MICROBLAZE_TEXTREL_64, 31) /* TEXT Entry offset 64-bit. */
656 RELOC_NUMBER (R_MICROBLAZE_TEXTREL_32_LO, 32) /* TEXT Entry offset 32-bit. */
657 RELOC_NUMBER (R_MICROBLAZE_32_NONE, 33)
658+ RELOC_NUMBER (R_MICROBLAZE_IMML_64, 34)
659+ RELOC_NUMBER (R_MICROBLAZE_GPC_64, 35) /* GOT entry offset. */
660
661 END_RELOC_NUMBERS (R_MICROBLAZE_max)
662
663diff --git a/opcodes/microblaze-opc.h b/opcodes/microblaze-opc.h
664index 985834b..9b6264b 100644
665--- a/opcodes/microblaze-opc.h
666+++ b/opcodes/microblaze-opc.h
667@@ -538,8 +538,8 @@ struct op_code_struct
668 {"llr", INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xC8000300, OPCODE_MASK_H4, llr, memory_load_inst },
669 {"sl", INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xD8000100, OPCODE_MASK_H4, sl, memory_store_inst },
670 {"slr", INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xD8000300, OPCODE_MASK_H4, slr, memory_store_inst },
671- {"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 */
672- {"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 */
673+ {"lli", INST_TYPE_RD_R1_IMM, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xEC000000, OPCODE_MASK_H, invalid_inst, memory_load_inst }, /* Identical to 32-bit */
674+ {"sli", INST_TYPE_RD_R1_IMM, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xFC000000, OPCODE_MASK_H, invalid_inst, memory_store_inst }, /* Identical to 32-bit */
675 {"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 */
676 {"dadd", INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x58000400, OPCODE_MASK_H4, dadd, arithmetic_inst },
677 {"drsub", INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x58000480, OPCODE_MASK_H4, drsub, arithmetic_inst },
678diff --git a/opcodes/microblaze-opcm.h b/opcodes/microblaze-opcm.h
679index 076dbcd..5f2e190 100644
680--- a/opcodes/microblaze-opcm.h
681+++ b/opcodes/microblaze-opcm.h
682@@ -40,8 +40,8 @@ enum microblaze_instr
683 imm, rtsd, rtid, rtbd, rted, bri, brid, brlid, brai, braid, bralid,
684 brki, beqi, beqid, bnei, bneid, blti, bltid, blei, bleid, bgti,
685 bgtid, bgei, bgeid, lbu, lbuea, lbur, lhu, lhuea, lhur, lw, lwea, lwr, lwx,
686- sb, sbea, sbr, sh, shea, shr, sw, swea, swr, swx, lbui, lhui, lwi,
687- sbi, shi, swi, msrset, msrclr, tuqula, fadd, frsub, fmul, fdiv,
688+ sb, sbea, sbr, sh, shea, shr, sw, swea, swr, swx, lbui, lhui, lwi, lli,
689+ sbi, shi, sli, swi, msrset, msrclr, tuqula, fadd, frsub, fmul, fdiv,
690 fcmp_lt, fcmp_eq, fcmp_le, fcmp_gt, fcmp_ne, fcmp_ge, fcmp_un, flt,
691 fint, fsqrt,
692 tget, tcget, tnget, tncget, tput, tcput, tnput, tncput,