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