Brad Bishop | 26bdd44 | 2019-08-16 17:08:17 -0400 | [diff] [blame^] | 1 | From 616031595c692c2181c3b1ce8c08678b68b2fe4e 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] -Fixed MB-x relocation issues -Added imml for required MB-x |
| 5 | instructions |
| 6 | |
| 7 | Signed-off-by: Mahesh Bodapati <mbodapat@xilinx.com> |
| 8 | Signed-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 | |
| 16 | diff --git a/bfd/elf64-microblaze.c b/bfd/elf64-microblaze.c |
| 17 | index 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); |
| 118 | diff --git a/gas/config/tc-microblaze.c b/gas/config/tc-microblaze.c |
| 119 | index 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; |
| 361 | diff --git a/gas/tc.h b/gas/tc.h |
| 362 | index 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 *); |