blob: 55319ee2cfe5528dfdcf21b6560e5b5323933b70 [file] [log] [blame]
Brad Bishop26bdd442019-08-16 17:08:17 -04001From 616031595c692c2181c3b1ce8c08678b68b2fe4e Mon Sep 17 00:00:00 2001
2From: Nagaraju Mekala <nmekala@xilix.com>
3Date: Fri, 28 Sep 2018 12:04:55 +0530
4Subject: [PATCH] -Fixed MB-x relocation issues -Added imml for required MB-x
5 instructions
6
7Signed-off-by: Mahesh Bodapati <mbodapat@xilinx.com>
8Signed-off-by: Nagaraju Mekala <nagaraju.mekala@xilinx.com>
9
10---
11 bfd/elf64-microblaze.c | 68 ++++++++++++++++----
12 gas/config/tc-microblaze.c | 152 ++++++++++++++++++++++++++++++++-------------
13 gas/tc.h | 2 +-
14 3 files changed, 167 insertions(+), 55 deletions(-)
15
16diff --git a/bfd/elf64-microblaze.c b/bfd/elf64-microblaze.c
17index 56a45f2..54a2461 100644
18--- a/bfd/elf64-microblaze.c
19+++ b/bfd/elf64-microblaze.c
20@@ -1476,8 +1476,17 @@ microblaze_elf_relocate_section (bfd *output_bfd,
21 relocation -= (input_section->output_section->vma
22 + input_section->output_offset
23 + offset + INST_WORD_SIZE);
24- bfd_put_16 (input_bfd, (relocation >> 16) & 0xffff,
25+ unsigned long insn = bfd_get_32 (input_bfd, contents + offset +endian);
26+ if (insn == 0xb2000000 || insn == 0xb2ffffff)
27+ {
28+ insn &= ~0x00ffffff;
29+ insn |= (relocation >> 16) & 0xffffff;
30+ bfd_put_32 (input_bfd, insn,
31 contents + offset + endian);
32+ }
33+ else
34+ bfd_put_16 (input_bfd, (relocation >> 16) & 0xffff,
35+ contents + offset + endian);
36 bfd_put_16 (input_bfd, relocation & 0xffff,
37 contents + offset + endian + INST_WORD_SIZE);
38 }
39@@ -1567,11 +1576,28 @@ microblaze_elf_relocate_section (bfd *output_bfd,
40 else
41 {
42 if (r_type == R_MICROBLAZE_64_PCREL)
43- relocation -= (input_section->output_section->vma
44- + input_section->output_offset
45- + offset + INST_WORD_SIZE);
46- bfd_put_16 (input_bfd, (relocation >> 16) & 0xffff,
47+ {
48+ if (!input_section->output_section->vma &&
49+ !input_section->output_offset && !offset)
50+ relocation -= (input_section->output_section->vma
51+ + input_section->output_offset
52+ + offset);
53+ else
54+ relocation -= (input_section->output_section->vma
55+ + input_section->output_offset
56+ + offset + INST_WORD_SIZE);
57+ }
58+ unsigned long insn = bfd_get_32 (input_bfd, contents + offset +endian);
59+ if (insn == 0xb2000000 || insn == 0xb2ffffff)
60+ {
61+ insn &= ~0x00ffffff;
62+ insn |= (relocation >> 16) & 0xffffff;
63+ bfd_put_32 (input_bfd, insn,
64 contents + offset + endian);
65+ }
66+ else
67+ bfd_put_16 (input_bfd, (relocation >> 16) & 0xffff,
68+ contents + offset + endian);
69 bfd_put_16 (input_bfd, relocation & 0xffff,
70 contents + offset + endian + INST_WORD_SIZE);
71 }
72@@ -1690,9 +1716,19 @@ static void
73 microblaze_bfd_write_imm_value_32 (bfd *abfd, bfd_byte *bfd_addr, bfd_vma val)
74 {
75 unsigned long instr = bfd_get_32 (abfd, bfd_addr);
76- instr &= ~0x0000ffff;
77- instr |= (val & 0x0000ffff);
78- bfd_put_32 (abfd, instr, bfd_addr);
79+
80+ if (instr == 0xb2000000 || instr == 0xb2ffffff)
81+ {
82+ instr &= ~0x00ffffff;
83+ instr |= (val & 0xffffff);
84+ bfd_put_32 (abfd, instr, bfd_addr);
85+ }
86+ else
87+ {
88+ instr &= ~0x0000ffff;
89+ instr |= (val & 0x0000ffff);
90+ bfd_put_32 (abfd, instr, bfd_addr);
91+ }
92 }
93
94 /* Read-modify-write into the bfd, an immediate value into appropriate fields of
95@@ -1704,10 +1740,18 @@ microblaze_bfd_write_imm_value_64 (bfd *abfd, bfd_byte *bfd_addr, bfd_vma val)
96 unsigned long instr_lo;
97
98 instr_hi = bfd_get_32 (abfd, bfd_addr);
99- instr_hi &= ~0x0000ffff;
100- instr_hi |= ((val >> 16) & 0x0000ffff);
101- bfd_put_32 (abfd, instr_hi, bfd_addr);
102-
103+ if (instr_hi == 0xb2000000 || instr_hi == 0xb2ffffff)
104+ {
105+ instr_hi &= ~0x00ffffff;
106+ instr_hi |= (val >> 16) & 0xffffff;
107+ bfd_put_32 (abfd, instr_hi,bfd_addr);
108+ }
109+ else
110+ {
111+ instr_hi &= ~0x0000ffff;
112+ instr_hi |= ((val >> 16) & 0x0000ffff);
113+ bfd_put_32 (abfd, instr_hi, bfd_addr);
114+ }
115 instr_lo = bfd_get_32 (abfd, bfd_addr + INST_WORD_SIZE);
116 instr_lo &= ~0x0000ffff;
117 instr_lo |= (val & 0x0000ffff);
118diff --git a/gas/config/tc-microblaze.c b/gas/config/tc-microblaze.c
119index 587a4d5..fa437b6 100644
120--- a/gas/config/tc-microblaze.c
121+++ b/gas/config/tc-microblaze.c
122@@ -392,7 +392,7 @@ microblaze_s_weakext (int ignore ATTRIBUTE_UNUSED)
123 Integer arg to pass to the function. */
124 /* If the pseudo-op is not found in this table, it searches in the obj-elf.c,
125 and then in the read.c table. */
126-const pseudo_typeS md_pseudo_table[] =
127+pseudo_typeS md_pseudo_table[] =
128 {
129 {"lcomm", microblaze_s_lcomm, 1},
130 {"data", microblaze_s_data, 0},
131@@ -401,7 +401,7 @@ const pseudo_typeS md_pseudo_table[] =
132 {"data32", cons, 4}, /* Same as word. */
133 {"ent", s_func, 0}, /* Treat ent as function entry point. */
134 {"end", microblaze_s_func, 1}, /* Treat end as function end point. */
135- {"gpword", s_rva, 8}, /* gpword label => store resolved label address in data section. */
136+ {"gpword", s_rva, 4}, /* gpword label => store resolved label address in data section. */
137 {"gpdword", s_rva, 8}, /* gpword label => store resolved label address in data section. */
138 {"weakext", microblaze_s_weakext, 0},
139 {"rodata", microblaze_s_rdata, 0},
140@@ -996,7 +996,7 @@ md_assemble (char * str)
141 unsigned reg2;
142 unsigned reg3;
143 unsigned isize;
144- unsigned int immed, immed2, temp;
145+ unsigned long immed, immed2, temp;
146 expressionS exp;
147 char name[20];
148 long immedl;
149@@ -1118,8 +1118,9 @@ md_assemble (char * str)
150 as_fatal (_("lmi pseudo instruction should not use a label in imm field"));
151 else if (streq (name, "smi"))
152 as_fatal (_("smi pseudo instruction should not use a label in imm field"));
153-
154- if (reg2 == REG_ROSDP)
155+ if(streq (name, "lli") || streq (name, "sli"))
156+ opc = str_microblaze_64;
157+ else if (reg2 == REG_ROSDP)
158 opc = str_microblaze_ro_anchor;
159 else if (reg2 == REG_RWSDP)
160 opc = str_microblaze_rw_anchor;
161@@ -1182,31 +1183,55 @@ md_assemble (char * str)
162 inst |= (immed << IMM_LOW) & IMM_MASK;
163 }
164 }
165- else
166- {
167- temp = immed & 0xFFFF8000;
168- if ((temp != 0) && (temp != 0xFFFF8000))
169- {
170+ else if (streq (name, "lli") || streq (name, "sli"))
171+ {
172+ temp = immed & 0xFFFFFF8000;
173+ if (temp != 0 && temp != 0xFFFFFF8000)
174+ {
175 /* Needs an immediate inst. */
176- opcode1 = (struct op_code_struct *) hash_find (opcode_hash_control, "imm");
177+ opcode1 = (struct op_code_struct *) hash_find (opcode_hash_control, "imml");
178 if (opcode1 == NULL)
179 {
180- as_bad (_("unknown opcode \"%s\""), "imm");
181+ as_bad (_("unknown opcode \"%s\""), "imml");
182 return;
183 }
184-
185 inst1 = opcode1->bit_sequence;
186- inst1 |= ((immed & 0xFFFF0000) >> 16) & IMM_MASK;
187+ inst1 |= ((immed & 0xFFFFFFFFFFFF0000L) >> 16) & IMML_MASK;
188 output[0] = INST_BYTE0 (inst1);
189 output[1] = INST_BYTE1 (inst1);
190 output[2] = INST_BYTE2 (inst1);
191 output[3] = INST_BYTE3 (inst1);
192 output = frag_more (isize);
193- }
194- inst |= (reg1 << RD_LOW) & RD_MASK;
195- inst |= (reg2 << RA_LOW) & RA_MASK;
196- inst |= (immed << IMM_LOW) & IMM_MASK;
197- }
198+ }
199+ inst |= (reg1 << RD_LOW) & RD_MASK;
200+ inst |= (reg2 << RA_LOW) & RA_MASK;
201+ inst |= (immed << IMM_LOW) & IMM_MASK;
202+ }
203+ else
204+ {
205+ temp = immed & 0xFFFF8000;
206+ if ((temp != 0) && (temp != 0xFFFF8000))
207+ {
208+ /* Needs an immediate inst. */
209+ opcode1 = (struct op_code_struct *) hash_find (opcode_hash_control, "imm");
210+ if (opcode1 == NULL)
211+ {
212+ as_bad (_("unknown opcode \"%s\""), "imm");
213+ return;
214+ }
215+
216+ inst1 = opcode1->bit_sequence;
217+ inst1 |= ((immed & 0xFFFF0000) >> 16) & IMM_MASK;
218+ output[0] = INST_BYTE0 (inst1);
219+ output[1] = INST_BYTE1 (inst1);
220+ output[2] = INST_BYTE2 (inst1);
221+ output[3] = INST_BYTE3 (inst1);
222+ output = frag_more (isize);
223+ }
224+ inst |= (reg1 << RD_LOW) & RD_MASK;
225+ inst |= (reg2 << RA_LOW) & RA_MASK;
226+ inst |= (immed << IMM_LOW) & IMM_MASK;
227+ }
228 break;
229
230 case INST_TYPE_RD_R1_IMMS:
231@@ -1832,12 +1857,20 @@ md_assemble (char * str)
232 case INST_TYPE_IMM:
233 if (streq (name, "imm"))
234 as_fatal (_("An IMM instruction should not be present in the .s file"));
235-
236- op_end = parse_imm (op_end + 1, & exp, MIN_IMM, MAX_IMM);
237+ if (microblaze_arch_size == 64)
238+ op_end = parse_imml (op_end + 1, & exp, MIN_IMML, MAX_IMML);
239+ else
240+ op_end = parse_imm (op_end + 1, & exp, MIN_IMM, MAX_IMM);
241
242 if (exp.X_op != O_constant)
243 {
244- char *opc = NULL;
245+ char *opc;
246+ if (microblaze_arch_size == 64 && (streq (name, "breai") ||
247+ streq (name, "breaid") ||
248+ streq (name, "brai") || streq (name, "braid")))
249+ opc = str_microblaze_64;
250+ else
251+ opc = NULL;
252 relax_substateT subtype;
253
254 if (exp.X_md != 0)
255@@ -1860,27 +1893,54 @@ md_assemble (char * str)
256 immed = exp.X_add_number;
257 }
258
259+ if (microblaze_arch_size == 64 && (streq (name, "breai") ||
260+ streq (name, "breaid") ||
261+ streq (name, "brai") || streq (name, "braid")))
262+ {
263+ temp = immed & 0xFFFFFF8000;
264+ if (temp != 0)
265+ {
266+ /* Needs an immediate inst. */
267+ opcode1 = (struct op_code_struct *) hash_find (opcode_hash_control, "imml");
268+ if (opcode1 == NULL)
269+ {
270+ as_bad (_("unknown opcode \"%s\""), "imml");
271+ return;
272+ }
273
274- temp = immed & 0xFFFF8000;
275- if ((temp != 0) && (temp != 0xFFFF8000))
276- {
277- /* Needs an immediate inst. */
278- opcode1 = (struct op_code_struct *) hash_find (opcode_hash_control, "imm");
279- if (opcode1 == NULL)
280- {
281- as_bad (_("unknown opcode \"%s\""), "imm");
282- return;
283+ inst1 = opcode1->bit_sequence;
284+ inst1 |= ((immed & 0xFFFFFFFFFFFF0000L) >> 16) & IMML_MASK;
285+ output[0] = INST_BYTE0 (inst1);
286+ output[1] = INST_BYTE1 (inst1);
287+ output[2] = INST_BYTE2 (inst1);
288+ output[3] = INST_BYTE3 (inst1);
289+ output = frag_more (isize);
290 }
291+ inst |= (immed << IMM_LOW) & IMM_MASK;
292+ }
293+ else
294+ {
295+ temp = immed & 0xFFFF8000;
296+ if ((temp != 0) && (temp != 0xFFFF8000))
297+ {
298+ /* Needs an immediate inst. */
299+ opcode1 = (struct op_code_struct *) hash_find (opcode_hash_control, "imm");
300+ if (opcode1 == NULL)
301+ {
302+ as_bad (_("unknown opcode \"%s\""), "imm");
303+ return;
304+ }
305
306- inst1 = opcode1->bit_sequence;
307- inst1 |= ((immed & 0xFFFF0000) >> 16) & IMM_MASK;
308- output[0] = INST_BYTE0 (inst1);
309- output[1] = INST_BYTE1 (inst1);
310- output[2] = INST_BYTE2 (inst1);
311- output[3] = INST_BYTE3 (inst1);
312- output = frag_more (isize);
313- }
314- inst |= (immed << IMM_LOW) & IMM_MASK;
315+ inst1 = opcode1->bit_sequence;
316+ inst1 |= ((immed & 0xFFFF0000) >> 16) & IMM_MASK;
317+ output[0] = INST_BYTE0 (inst1);
318+ output[1] = INST_BYTE1 (inst1);
319+ output[2] = INST_BYTE2 (inst1);
320+ output[3] = INST_BYTE3 (inst1);
321+ output = frag_more (isize);
322+ }
323+ inst |= (immed << IMM_LOW) & IMM_MASK;
324+ }
325 break;
326
327 case INST_TYPE_NONE:
328@@ -2460,7 +2520,7 @@ md_apply_fix (fixS * fixP,
329
330 inst1 = opcode1->bit_sequence;
331 if (fixP->fx_addsy == NULL || S_IS_DEFINED (fixP->fx_addsy))
332- inst1 |= ((val & 0xFFFFFFFFFFFF0000L) >> 16) & IMML_MASK;
333+ inst1 |= ((val & 0xFFFFFF0000L) >> 16) & IMML_MASK;
334 if (fixP->fx_r_type == BFD_RELOC_MICROBLAZE_64)
335 fixP->fx_r_type = BFD_RELOC_64;
336 if (fixP->fx_r_type == BFD_RELOC_MICROBLAZE_64_PCREL)
337@@ -2628,7 +2688,14 @@ md_estimate_size_before_relax (fragS * fragP,
338 }
339 else
340 {
341- fragP->fr_subtype = UNDEFINED_PC_OFFSET;
342+ if (fragP->fr_opcode != NULL) {
343+ if (streq (fragP->fr_opcode, str_microblaze_64))
344+ fragP->fr_subtype = DEFINED_64_PC_OFFSET;
345+ else
346+ fragP->fr_subtype = UNDEFINED_PC_OFFSET;
347+ }
348+ else
349+ fragP->fr_subtype = UNDEFINED_PC_OFFSET;
350 fragP->fr_var = INST_WORD_SIZE*2;
351 }
352 break;
353@@ -2905,6 +2972,7 @@ md_parse_option (int c, const char * arg ATTRIBUTE_UNUSED)
354 case OPTION_M64:
355 //if (arg != NULL && strcmp (arg, "64") == 0)
356 microblaze_arch_size = 64;
357+ md_pseudo_table[7].poc_val = 8;
358 break;
359 default:
360 return 0;
361diff --git a/gas/tc.h b/gas/tc.h
362index 0a50a69..529a73b 100644
363--- a/gas/tc.h
364+++ b/gas/tc.h
365@@ -22,7 +22,7 @@
366 /* In theory (mine, at least!) the machine dependent part of the assembler
367 should only have to include one file. This one. -- JF */
368
369-extern const pseudo_typeS md_pseudo_table[];
370+extern pseudo_typeS md_pseudo_table[];
371
372 const char * md_atof (int, char *, int *);
373 int md_parse_option (int, const char *);