Brad Bishop | f6355e4 | 2020-12-08 14:30:50 -0500 | [diff] [blame^] | 1 | From 5b1793fe6dfb16755f584821023145bdfc4b55d7 Mon Sep 17 00:00:00 2001 |
| 2 | From: Nagaraju Mekala <nmekala@xilix.com> |
| 3 | Date: Fri, 28 Sep 2018 12:04:55 +0530 |
| 4 | Subject: [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 | |
| 13 | diff --git a/bfd/elf64-microblaze.c b/bfd/elf64-microblaze.c |
| 14 | index 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); |
| 115 | diff --git a/gas/config/tc-microblaze.c b/gas/config/tc-microblaze.c |
| 116 | index 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; |
| 358 | diff --git a/gas/tc.h b/gas/tc.h |
| 359 | index 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 | -- |
| 372 | 2.17.1 |
| 373 | |