From 05240f6bdb5e3789efdc03b90c073b78785268e4 Mon Sep 17 00:00:00 2001 From: Nagaraju Mekala Date: Sun, 30 Sep 2018 16:31:26 +0530 Subject: [PATCH 16/31] MB-X initial commit code cleanup is needed. Signed-off-by: Mahesh Bodapati Signed-off-by: Nagaraju Mekala --- bfd/bfd-in2.h | 10 +++ bfd/elf32-microblaze.c | 65 +++++++++++++++++-- bfd/elf64-microblaze.c | 61 +++++++++++++++++- bfd/libbfd.h | 2 + bfd/reloc.c | 12 ++++ gas/config/tc-microblaze.c | 152 +++++++++++++++++++++++++++++++++++++-------- include/elf/microblaze.h | 2 + opcodes/microblaze-opc.h | 4 +- opcodes/microblaze-opcm.h | 4 +- 9 files changed, 277 insertions(+), 35 deletions(-) diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h index 5807f70..44cddc2 100644 --- a/bfd/bfd-in2.h +++ b/bfd/bfd-in2.h @@ -5801,11 +5801,21 @@ done here - only used for relaxing */ BFD_RELOC_MICROBLAZE_64_NONE, /* This is a 64 bit reloc that stores the 32 bit pc relative + * +value in two words (with an imml instruction). No relocation is + * +done here - only used for relaxing */ + BFD_RELOC_MICROBLAZE_64, + +/* This is a 64 bit reloc that stores the 32 bit pc relative value in two words (with an imm instruction). The relocation is PC-relative GOT offset */ BFD_RELOC_MICROBLAZE_64_GOTPC, /* This is a 64 bit reloc that stores the 32 bit pc relative +value in two words (with an imml instruction). The relocation is +PC-relative GOT offset */ + BFD_RELOC_MICROBLAZE_64_GPC, + +/* This is a 64 bit reloc that stores the 32 bit pc relative value in two words (with an imm instruction). The relocation is GOT offset */ BFD_RELOC_MICROBLAZE_64_GOT, diff --git a/bfd/elf32-microblaze.c b/bfd/elf32-microblaze.c index 94fa3cf..b632dd1 100644 --- a/bfd/elf32-microblaze.c +++ b/bfd/elf32-microblaze.c @@ -116,6 +116,20 @@ static reloc_howto_type microblaze_elf_howto_raw[] = 0x0000ffff, /* Dest Mask. */ TRUE), /* PC relative offset? */ + HOWTO (R_MICROBLAZE_IMML_64, /* Type. */ + 0, /* Rightshift. */ + 2, /* Size (0 = byte, 1 = short, 2 = long). */ + 16, /* Bitsize. */ + TRUE, /* PC_relative. */ + 0, /* Bitpos. */ + complain_overflow_dont, /* Complain on overflow. */ + bfd_elf_generic_reloc,/* Special Function. */ + "R_MICROBLAZE_IMML_64", /* Name. */ + FALSE, /* Partial Inplace. */ + 0, /* Source Mask. */ + 0x0000ffff, /* Dest Mask. */ + FALSE), /* PC relative offset? */ + /* A 64 bit relocation. Table entry not really used. */ HOWTO (R_MICROBLAZE_64, /* Type. */ 0, /* Rightshift. */ @@ -280,6 +294,21 @@ static reloc_howto_type microblaze_elf_howto_raw[] = 0x0000ffff, /* Dest Mask. */ TRUE), /* PC relative offset? */ + /* A 64 bit GOTPC relocation. Table-entry not really used. */ + HOWTO (R_MICROBLAZE_GPC_64, /* Type. */ + 0, /* Rightshift. */ + 2, /* Size (0 = byte, 1 = short, 2 = long). */ + 16, /* Bitsize. */ + TRUE, /* PC_relative. */ + 0, /* Bitpos. */ + complain_overflow_dont, /* Complain on overflow. */ + bfd_elf_generic_reloc, /* Special Function. */ + "R_MICROBLAZE_GPC_64", /* Name. */ + FALSE, /* Partial Inplace. */ + 0, /* Source Mask. */ + 0x0000ffff, /* Dest Mask. */ + TRUE), /* PC relative offset? */ + /* A 64 bit GOT relocation. Table-entry not really used. */ HOWTO (R_MICROBLAZE_GOT_64, /* Type. */ 0, /* Rightshift. */ @@ -619,9 +648,15 @@ microblaze_elf_reloc_type_lookup (bfd * abfd ATTRIBUTE_UNUSED, case BFD_RELOC_VTABLE_ENTRY: microblaze_reloc = R_MICROBLAZE_GNU_VTENTRY; break; + case BFD_RELOC_MICROBLAZE_64: + microblaze_reloc = R_MICROBLAZE_IMML_64; + break; case BFD_RELOC_MICROBLAZE_64_GOTPC: microblaze_reloc = R_MICROBLAZE_GOTPC_64; break; + case BFD_RELOC_MICROBLAZE_64_GPC: + microblaze_reloc = R_MICROBLAZE_GPC_64; + break; case BFD_RELOC_MICROBLAZE_64_GOT: microblaze_reloc = R_MICROBLAZE_GOT_64; break; @@ -1467,7 +1502,7 @@ microblaze_elf_relocate_section (bfd *output_bfd, if (r_symndx == STN_UNDEF || (input_section->flags & SEC_ALLOC) == 0) { relocation += addend; - if (r_type == R_MICROBLAZE_32) + if (r_type == R_MICROBLAZE_32)// || r_type == R_MICROBLAZE_IMML_64) bfd_put_32 (input_bfd, relocation, contents + offset); else { @@ -1933,6 +1968,28 @@ microblaze_elf_relax_section (bfd *abfd, irel->r_addend -= calc_fixup (irel->r_addend, 0, sec); } break; + case R_MICROBLAZE_IMML_64: + { + /* This was a PC-relative instruction that was + completely resolved. */ + int sfix, efix; + unsigned int val; + bfd_vma target_address; + target_address = irel->r_addend + irel->r_offset; + sfix = calc_fixup (irel->r_offset, 0, sec); + efix = calc_fixup (target_address, 0, sec); + + /* Validate the in-band val. */ + val = bfd_get_32 (abfd, contents + irel->r_offset); + if (val != irel->r_addend && ELF64_R_TYPE (irel->r_info) == R_MICROBLAZE_32_NONE) { + fprintf(stderr, "%d: CORRUPT relax reloc %x %lx\n", __LINE__, val, irel->r_addend); + } + irel->r_addend -= (efix - sfix); + /* Should use HOWTO. */ + microblaze_bfd_write_imm_value_64 (abfd, contents + irel->r_offset, + irel->r_addend); + } + break; case R_MICROBLAZE_NONE: case R_MICROBLAZE_32_NONE: { @@ -2037,9 +2094,9 @@ microblaze_elf_relax_section (bfd *abfd, microblaze_bfd_write_imm_value_32 (abfd, ocontents + irelscan->r_offset, irelscan->r_addend); } - if (ELF32_R_TYPE (irelscan->r_info) == (int) R_MICROBLAZE_32) - { - isym = isymbuf + ELF32_R_SYM (irelscan->r_info); + if (ELF32_R_TYPE (irelscan->r_info) == (int) R_MICROBLAZE_32)// || ELF32_R_TYPE (irelscan->r_info) == (int) R_MICROBLAZE_IMML_64) + { + isym = isymbuf + ELF32_R_SYM (irelscan->r_info); /* Look at the reloc only if the value has been resolved. */ if (isym->st_shndx == shndx diff --git a/bfd/elf64-microblaze.c b/bfd/elf64-microblaze.c index 0f43ae6..56a45f2 100644 --- a/bfd/elf64-microblaze.c +++ b/bfd/elf64-microblaze.c @@ -117,6 +117,21 @@ static reloc_howto_type microblaze_elf_howto_raw[] = TRUE), /* PC relative offset? */ /* A 64 bit relocation. Table entry not really used. */ + HOWTO (R_MICROBLAZE_IMML_64, /* Type. */ + 0, /* Rightshift. */ + 4, /* Size (0 = byte, 1 = short, 2 = long). */ + 64, /* Bitsize. */ + TRUE, /* PC_relative. */ + 0, /* Bitpos. */ + complain_overflow_dont, /* Complain on overflow. */ + bfd_elf_generic_reloc,/* Special Function. */ + "R_MICROBLAZE_IMML_64", /* Name. */ + FALSE, /* Partial Inplace. */ + 0, /* Source Mask. */ + 0x0000ffff, /* Dest Mask. */ + TRUE), /* PC relative offset? */ + + /* A 64 bit relocation. Table entry not really used. */ HOWTO (R_MICROBLAZE_64, /* Type. */ 0, /* Rightshift. */ 2, /* Size (0 = byte, 1 = short, 2 = long). */ @@ -265,6 +280,21 @@ static reloc_howto_type microblaze_elf_howto_raw[] = 0x0000ffff, /* Dest Mask. */ TRUE), /* PC relative offset? */ + /* A 64 bit GOTPC relocation. Table-entry not really used. */ + HOWTO (R_MICROBLAZE_GPC_64, /* Type. */ + 0, /* Rightshift. */ + 2, /* Size (0 = byte, 1 = short, 2 = long). */ + 16, /* Bitsize. */ + TRUE, /* PC_relative. */ + 0, /* Bitpos. */ + complain_overflow_dont, /* Complain on overflow. */ + bfd_elf_generic_reloc, /* Special Function. */ + "R_MICROBLAZE_GPC_64", /* Name. */ + FALSE, /* Partial Inplace. */ + 0, /* Source Mask. */ + 0x0000ffff, /* Dest Mask. */ + TRUE), /* PC relative offset? */ + /* A 64 bit GOT relocation. Table-entry not really used. */ HOWTO (R_MICROBLAZE_GOT_64, /* Type. */ 0, /* Rightshift. */ @@ -589,9 +619,15 @@ microblaze_elf_reloc_type_lookup (bfd * abfd ATTRIBUTE_UNUSED, case BFD_RELOC_VTABLE_ENTRY: microblaze_reloc = R_MICROBLAZE_GNU_VTENTRY; break; + case BFD_RELOC_MICROBLAZE_64: + microblaze_reloc = R_MICROBLAZE_IMML_64; + break; case BFD_RELOC_MICROBLAZE_64_GOTPC: microblaze_reloc = R_MICROBLAZE_GOTPC_64; break; + case BFD_RELOC_MICROBLAZE_64_GPC: + microblaze_reloc = R_MICROBLAZE_GPC_64; + break; case BFD_RELOC_MICROBLAZE_64_GOT: microblaze_reloc = R_MICROBLAZE_GOT_64; break; @@ -1161,6 +1197,7 @@ microblaze_elf_relocate_section (bfd *output_bfd, break; /* Do nothing. */ case (int) R_MICROBLAZE_GOTPC_64: + case (int) R_MICROBLAZE_GPC_64: relocation = htab->sgotplt->output_section->vma + htab->sgotplt->output_offset; relocation -= (input_section->output_section->vma @@ -1431,7 +1468,7 @@ microblaze_elf_relocate_section (bfd *output_bfd, if (r_symndx == STN_UNDEF || (input_section->flags & SEC_ALLOC) == 0) { relocation += addend; - if (r_type == R_MICROBLAZE_32) + if (r_type == R_MICROBLAZE_32)// || r_type == R_MICROBLAZE_IMML_64) bfd_put_32 (input_bfd, relocation, contents + offset); else { @@ -1876,6 +1913,28 @@ microblaze_elf_relax_section (bfd *abfd, irel->r_addend -= calc_fixup (irel->r_addend, 0, sec); } break; + case R_MICROBLAZE_IMML_64: + { + /* This was a PC-relative instruction that was + completely resolved. */ + int sfix, efix; + unsigned int val; + bfd_vma target_address; + target_address = irel->r_addend + irel->r_offset; + sfix = calc_fixup (irel->r_offset, 0, sec); + efix = calc_fixup (target_address, 0, sec); + + /* Validate the in-band val. */ + val = bfd_get_32 (abfd, contents + irel->r_offset); + if (val != irel->r_addend && ELF64_R_TYPE (irel->r_info) == R_MICROBLAZE_32_NONE) { + fprintf(stderr, "%d: CORRUPT relax reloc %x %lx\n", __LINE__, val, irel->r_addend); + } + irel->r_addend -= (efix - sfix); + /* Should use HOWTO. */ + microblaze_bfd_write_imm_value_64 (abfd, contents + irel->r_offset, + irel->r_addend); + } + break; case R_MICROBLAZE_NONE: case R_MICROBLAZE_32_NONE: { diff --git a/bfd/libbfd.h b/bfd/libbfd.h index 261086c..d7892a6 100644 --- a/bfd/libbfd.h +++ b/bfd/libbfd.h @@ -2864,7 +2864,9 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@", "BFD_RELOC_MICROBLAZE_32_SYM_OP_SYM", "BFD_RELOC_MICROBLAZE_32_NONE", "BFD_RELOC_MICROBLAZE_64_NONE", + "BFD_RELOC_MICROBLAZE_64", "BFD_RELOC_MICROBLAZE_64_GOTPC", + "BFD_RELOC_MICROBLAZE_64_GPC", "BFD_RELOC_MICROBLAZE_64_GOT", "BFD_RELOC_MICROBLAZE_64_PLT", "BFD_RELOC_MICROBLAZE_64_GOTOFF", diff --git a/bfd/reloc.c b/bfd/reloc.c index d89bc5d..60eac77 100644 --- a/bfd/reloc.c +++ b/bfd/reloc.c @@ -6873,6 +6873,12 @@ ENUMDOC ENUM BFD_RELOC_MICROBLAZE_64_NONE ENUMDOC + This is a 32 bit reloc that stores the 32 bit pc relative + value in two words (with an imml instruction). No relocation is + done here - only used for relaxing +ENUM + BFD_RELOC_MICROBLAZE_64 +ENUMDOC This is a 64 bit reloc that stores the 32 bit pc relative value in two words (with an imm instruction). No relocation is done here - only used for relaxing @@ -6880,6 +6886,12 @@ ENUM BFD_RELOC_MICROBLAZE_64_GOTPC ENUMDOC This is a 64 bit reloc that stores the 32 bit pc relative + value in two words (with an imml instruction). No relocation is + done here - only used for relaxing +ENUM + BFD_RELOC_MICROBLAZE_64_GPC +ENUMDOC + This is a 64 bit reloc that stores the 32 bit pc relative value in two words (with an imm instruction). The relocation is PC-relative GOT offset ENUM diff --git a/gas/config/tc-microblaze.c b/gas/config/tc-microblaze.c index eb7998f..680a794 100644 --- a/gas/config/tc-microblaze.c +++ b/gas/config/tc-microblaze.c @@ -94,6 +94,7 @@ const char FLT_CHARS[] = "rRsSfFdDxXpP"; #define TLSTPREL_OFFSET 16 #define TEXT_OFFSET 17 #define TEXT_PC_OFFSET 18 +#define DEFINED_64_OFFSET 19 /* Initialize the relax table. */ const relax_typeS md_relax_table[] = @@ -117,6 +118,8 @@ const relax_typeS md_relax_table[] = { 0x7fffffff, 0x80000000, INST_WORD_SIZE*2, 0 }, /* 16: TLSTPREL_OFFSET. */ { 0x7fffffff, 0x80000000, INST_WORD_SIZE*2, 0 }, /* 17: TEXT_OFFSET. */ { 0x7fffffff, 0x80000000, INST_WORD_SIZE*2, 0 } /* 18: TEXT_PC_OFFSET. */ +// { 0x7fffffff, 0x80000000, INST_WORD_SIZE*2, 0 } /* 16: TLSTPREL_OFFSET. */ + { 0x7fffffffffffffff, 0x8000000000000000, INST_WORD_SIZE, 0 } /* 17: DEFINED_64_OFFSET. */ }; static struct hash_control * opcode_hash_control; /* Opcode mnemonics. */ @@ -396,7 +399,8 @@ const pseudo_typeS md_pseudo_table[] = {"data32", cons, 4}, /* Same as word. */ {"ent", s_func, 0}, /* Treat ent as function entry point. */ {"end", microblaze_s_func, 1}, /* Treat end as function end point. */ - {"gpword", s_rva, 4}, /* gpword label => store resolved label address in data section. */ + {"gpword", s_rva, 8}, /* gpword label => store resolved label address in data section. */ + {"gpdword", s_rva, 8}, /* gpword label => store resolved label address in data section. */ {"weakext", microblaze_s_weakext, 0}, {"rodata", microblaze_s_rdata, 0}, {"sdata2", microblaze_s_rdata, 1}, @@ -405,6 +409,7 @@ const pseudo_typeS md_pseudo_table[] = {"sbss", microblaze_s_bss, 1}, {"text", microblaze_s_text, 0}, {"word", cons, 4}, + {"dword", cons, 8}, {"frame", s_ignore, 0}, {"mask", s_ignore, 0}, /* Emitted by gcc. */ {NULL, NULL, 0} @@ -898,7 +903,7 @@ check_got (int * got_type, int * got_len) extern bfd_reloc_code_real_type parse_cons_expression_microblaze (expressionS *exp, int size) { - if (size == 4) + if (size == 4 || (microblaze_arch_size == 64 && size == 8)) { /* Handle @GOTOFF et.al. */ char *save, *gotfree_copy; @@ -930,6 +935,7 @@ parse_cons_expression_microblaze (expressionS *exp, int size) static const char * str_microblaze_ro_anchor = "RO"; static const char * str_microblaze_rw_anchor = "RW"; +static const char * str_microblaze_64 = "64"; static bfd_boolean check_spl_reg (unsigned * reg) @@ -1174,6 +1180,33 @@ md_assemble (char * str) inst |= (immed << IMM_LOW) & IMM_MASK; } } +#if 0 //revisit + else if (streq (name, "lli") || streq (name, "sli")) + { + temp = immed & 0xFFFFFFFFFFFF8000; + if ((temp != 0) && (temp != 0xFFFFFFFFFFFF8000)) + { + /* Needs an immediate inst. */ + opcode1 = (struct op_code_struct *) hash_find (opcode_hash_control, "imml"); + if (opcode1 == NULL) + { + as_bad (_("unknown opcode \"%s\""), "imml"); + return; + } + + inst1 = opcode1->bit_sequence; + inst1 |= ((immedl & 0xFFFFFFFFFFFF0000L) >> 16) & IMML_MASK; + output[0] = INST_BYTE0 (inst1); + output[1] = INST_BYTE1 (inst1); + output[2] = INST_BYTE2 (inst1); + output[3] = INST_BYTE3 (inst1); + output = frag_more (isize); + } + inst |= (reg1 << RD_LOW) & RD_MASK; + inst |= (reg2 << RA_LOW) & RA_MASK; + inst |= (immed << IMM_LOW) & IMM_MASK; + } +#endif else { temp = immed & 0xFFFF8000; @@ -1926,6 +1959,7 @@ md_assemble (char * str) if (exp.X_op != O_constant) { char *opc = NULL; + //char *opc = str_microblaze_64; relax_substateT subtype; if (exp.X_md != 0) @@ -1939,7 +1973,7 @@ md_assemble (char * str) subtype, /* PC-relative or not. */ exp.X_add_symbol, exp.X_add_number, - opc); + (char *) opc); immedl = 0L; } else @@ -1977,7 +2011,7 @@ md_assemble (char * str) reg1 = 0; } if (strcmp (op_end, "")) - op_end = parse_imml (op_end + 1, & exp, MIN_IMM, MAX_IMM); + op_end = parse_imml (op_end + 1, & exp, MIN_IMML, MAX_IMML); else as_fatal (_("Error in statement syntax")); @@ -1987,7 +2021,8 @@ md_assemble (char * str) if (exp.X_op != O_constant) { - char *opc = NULL; + //char *opc = NULL; + char *opc = str_microblaze_64; relax_substateT subtype; if (exp.X_md != 0) @@ -2001,14 +2036,13 @@ md_assemble (char * str) subtype, /* PC-relative or not. */ exp.X_add_symbol, exp.X_add_number, - opc); + (char *) opc); immedl = 0L; } else { output = frag_more (isize); immedl = exp.X_add_number; - opcode1 = (struct op_code_struct *) hash_find (opcode_hash_control, "imml"); if (opcode1 == NULL) { @@ -2187,13 +2221,23 @@ md_convert_frag (bfd * abfd ATTRIBUTE_UNUSED, fragP->fr_fix += INST_WORD_SIZE * 2; fragP->fr_var = 0; break; + case DEFINED_64_OFFSET: + if (fragP->fr_symbol == GOT_symbol) + fix_new (fragP, fragP->fr_fix, INST_WORD_SIZE, fragP->fr_symbol, + fragP->fr_offset, TRUE, BFD_RELOC_MICROBLAZE_64_GPC); + else + fix_new (fragP, fragP->fr_fix, INST_WORD_SIZE, fragP->fr_symbol, + fragP->fr_offset, TRUE, BFD_RELOC_MICROBLAZE_64); + fragP->fr_fix += INST_WORD_SIZE * 2; + fragP->fr_var = 0; + break; case DEFINED_ABS_SEGMENT: if (fragP->fr_symbol == GOT_symbol) fix_new (fragP, fragP->fr_fix, INST_WORD_SIZE * 2, fragP->fr_symbol, fragP->fr_offset, TRUE, BFD_RELOC_MICROBLAZE_64_GOTPC); else fix_new (fragP, fragP->fr_fix, INST_WORD_SIZE * 2, fragP->fr_symbol, - fragP->fr_offset, FALSE, BFD_RELOC_64); + fragP->fr_offset, TRUE, BFD_RELOC_64); fragP->fr_fix += INST_WORD_SIZE * 2; fragP->fr_var = 0; break; @@ -2416,22 +2460,38 @@ md_apply_fix (fixS * fixP, case BFD_RELOC_64_PCREL: case BFD_RELOC_64: case BFD_RELOC_MICROBLAZE_64_TEXTREL: + case BFD_RELOC_MICROBLAZE_64: /* Add an imm instruction. First save the current instruction. */ for (i = 0; i < INST_WORD_SIZE; i++) buf[i + INST_WORD_SIZE] = buf[i]; + if (fixP->fx_r_type == BFD_RELOC_MICROBLAZE_64) + { + /* Generate the imm instruction. */ + opcode1 = (struct op_code_struct *) hash_find (opcode_hash_control, "imml"); + if (opcode1 == NULL) + { + as_bad (_("unknown opcode \"%s\""), "imml"); + return; + } - /* Generate the imm instruction. */ - opcode1 = (struct op_code_struct *) hash_find (opcode_hash_control, "imm"); - if (opcode1 == NULL) - { - as_bad (_("unknown opcode \"%s\""), "imm"); - return; - } - - inst1 = opcode1->bit_sequence; - if (fixP->fx_addsy == NULL || S_IS_DEFINED (fixP->fx_addsy)) - inst1 |= ((val & 0xFFFF0000) >> 16) & IMM_MASK; - + inst1 = opcode1->bit_sequence; + if (fixP->fx_addsy == NULL || S_IS_DEFINED (fixP->fx_addsy)) + inst1 |= ((val & 0xFFFFFFFFFFFF0000L) >> 16) & IMML_MASK; + } + else + { + /* Generate the imm instruction. */ + opcode1 = (struct op_code_struct *) hash_find (opcode_hash_control, "imm"); + if (opcode1 == NULL) + { + as_bad (_("unknown opcode \"%s\""), "imm"); + return; + } + + inst1 = opcode1->bit_sequence; + if (fixP->fx_addsy == NULL || S_IS_DEFINED (fixP->fx_addsy)) + inst1 |= ((val & 0xFFFF0000) >> 16) & IMM_MASK; + } buf[0] = INST_BYTE0 (inst1); buf[1] = INST_BYTE1 (inst1); buf[2] = INST_BYTE2 (inst1); @@ -2460,6 +2520,7 @@ md_apply_fix (fixS * fixP, /* Fall through. */ case BFD_RELOC_MICROBLAZE_64_GOTPC: + case BFD_RELOC_MICROBLAZE_64_GPC: case BFD_RELOC_MICROBLAZE_64_GOT: case BFD_RELOC_MICROBLAZE_64_PLT: case BFD_RELOC_MICROBLAZE_64_GOTOFF: @@ -2467,12 +2528,16 @@ md_apply_fix (fixS * fixP, /* Add an imm instruction. First save the current instruction. */ for (i = 0; i < INST_WORD_SIZE; i++) buf[i + INST_WORD_SIZE] = buf[i]; - - /* Generate the imm instruction. */ - opcode1 = (struct op_code_struct *) hash_find (opcode_hash_control, "imm"); + if (fixP->fx_r_type == BFD_RELOC_MICROBLAZE_64_GPC) + opcode1 = (struct op_code_struct *) hash_find (opcode_hash_control, "imml"); + else + opcode1 = (struct op_code_struct *) hash_find (opcode_hash_control, "imm"); if (opcode1 == NULL) { - as_bad (_("unknown opcode \"%s\""), "imm"); + if (fixP->fx_r_type == BFD_RELOC_MICROBLAZE_64_GPC) + as_bad (_("unknown opcode \"%s\""), "imml"); + else + as_bad (_("unknown opcode \"%s\""), "imm"); return; } @@ -2496,6 +2561,8 @@ md_apply_fix (fixS * fixP, moves code around due to relaxing. */ if (fixP->fx_r_type == BFD_RELOC_64_PCREL) fixP->fx_r_type = BFD_RELOC_MICROBLAZE_64_NONE; + if (fixP->fx_r_type == BFD_RELOC_MICROBLAZE_64) + fixP->fx_r_type = BFD_RELOC_MICROBLAZE_64_NONE; else if (fixP->fx_r_type == BFD_RELOC_32) fixP->fx_r_type = BFD_RELOC_MICROBLAZE_32_NONE; else @@ -2539,6 +2606,32 @@ md_estimate_size_before_relax (fragS * fragP, as_bad (_("Absolute PC-relative value in relaxation code. Assembler error.....")); abort (); } + else if (S_GET_SEGMENT (fragP->fr_symbol) == segment_type + && !S_IS_WEAK (fragP->fr_symbol)) + { + if (fragP->fr_opcode != NULL) { + if(streq (fragP->fr_opcode, str_microblaze_64)) + { + /* Used as an absolute value. */ + fragP->fr_subtype = DEFINED_64_OFFSET; + /* Variable part does not change. */ + fragP->fr_var = INST_WORD_SIZE; + } + else + { + fragP->fr_subtype = DEFINED_PC_OFFSET; + /* Don't know now whether we need an imm instruction. */ + fragP->fr_var = INST_WORD_SIZE; + } + } + else + { + fragP->fr_subtype = DEFINED_PC_OFFSET; + /* Don't know now whether we need an imm instruction. */ + fragP->fr_var = INST_WORD_SIZE; + } + } + #if 0 else if (S_GET_SEGMENT (fragP->fr_symbol) == segment_type && !S_IS_WEAK (fragP->fr_symbol)) { @@ -2546,6 +2639,7 @@ md_estimate_size_before_relax (fragS * fragP, /* Don't know now whether we need an imm instruction. */ fragP->fr_var = INST_WORD_SIZE; } +#endif else if (S_IS_DEFINED (fragP->fr_symbol) && (((S_GET_SEGMENT (fragP->fr_symbol))->flags & SEC_CODE) == 0)) { @@ -2648,6 +2742,7 @@ md_estimate_size_before_relax (fragS * fragP, case TLSLD_OFFSET: case TLSTPREL_OFFSET: case TLSDTPREL_OFFSET: + case DEFINED_64_OFFSET: fragP->fr_var = INST_WORD_SIZE*2; break; case DEFINED_RO_SEGMENT: @@ -2701,7 +2796,7 @@ md_pcrel_from_section (fixS * fixp, segT sec ATTRIBUTE_UNUSED) else { /* The case where we are going to resolve things... */ - if (fixp->fx_r_type == BFD_RELOC_64_PCREL) + if (fixp->fx_r_type == BFD_RELOC_64_PCREL ||fixp->fx_r_type == BFD_RELOC_MICROBLAZE_64) return fixp->fx_where + fixp->fx_frag->fr_address + INST_WORD_SIZE; else return fixp->fx_where + fixp->fx_frag->fr_address; @@ -2734,6 +2829,8 @@ tc_gen_reloc (asection * section ATTRIBUTE_UNUSED, fixS * fixp) case BFD_RELOC_MICROBLAZE_32_RWSDA: case BFD_RELOC_MICROBLAZE_32_SYM_OP_SYM: case BFD_RELOC_MICROBLAZE_64_GOTPC: + case BFD_RELOC_MICROBLAZE_64_GPC: + case BFD_RELOC_MICROBLAZE_64: case BFD_RELOC_MICROBLAZE_64_GOT: case BFD_RELOC_MICROBLAZE_64_PLT: case BFD_RELOC_MICROBLAZE_64_GOTOFF: @@ -2876,7 +2973,10 @@ cons_fix_new_microblaze (fragS * frag, r = BFD_RELOC_32; break; case 8: - r = BFD_RELOC_64; + if (microblaze_arch_size == 64) + r = BFD_RELOC_32; + else + r = BFD_RELOC_64; break; default: as_bad (_("unsupported BFD relocation size %u"), size); diff --git a/include/elf/microblaze.h b/include/elf/microblaze.h index 7bdba67..454e2b4 100644 --- a/include/elf/microblaze.h +++ b/include/elf/microblaze.h @@ -62,6 +62,8 @@ START_RELOC_NUMBERS (elf_microblaze_reloc_type) RELOC_NUMBER (R_MICROBLAZE_TEXTREL_64, 31) /* TEXT Entry offset 64-bit. */ RELOC_NUMBER (R_MICROBLAZE_TEXTREL_32_LO, 32) /* TEXT Entry offset 32-bit. */ RELOC_NUMBER (R_MICROBLAZE_32_NONE, 33) + RELOC_NUMBER (R_MICROBLAZE_IMML_64, 34) + RELOC_NUMBER (R_MICROBLAZE_GPC_64, 35) /* GOT entry offset. */ END_RELOC_NUMBERS (R_MICROBLAZE_max) diff --git a/opcodes/microblaze-opc.h b/opcodes/microblaze-opc.h index c88092d..8d43af0 100644 --- a/opcodes/microblaze-opc.h +++ b/opcodes/microblaze-opc.h @@ -538,8 +538,8 @@ struct op_code_struct {"llr", INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xC8000300, OPCODE_MASK_H4, llr, memory_load_inst }, {"sl", INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xD8000100, OPCODE_MASK_H4, sl, memory_store_inst }, {"slr", INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xD8000300, OPCODE_MASK_H4, slr, memory_store_inst }, - {"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 */ - {"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 */ + {"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 */ + {"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 */ {"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 */ {"dadd", INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x58000400, OPCODE_MASK_H4, dadd, arithmetic_inst }, {"drsub", INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x58000480, OPCODE_MASK_H4, drsub, arithmetic_inst }, diff --git a/opcodes/microblaze-opcm.h b/opcodes/microblaze-opcm.h index 265cea8..abb5c9f 100644 --- a/opcodes/microblaze-opcm.h +++ b/opcodes/microblaze-opcm.h @@ -40,8 +40,8 @@ enum microblaze_instr imm, rtsd, rtid, rtbd, rted, bri, brid, brlid, brai, braid, bralid, brki, beqi, beqid, bnei, bneid, blti, bltid, blei, bleid, bgti, bgtid, bgei, bgeid, lbu, lbuea, lbur, lhu, lhuea, lhur, lw, lwea, lwr, lwx, - sb, sbea, sbr, sh, shea, shr, sw, swea, swr, swx, lbui, lhui, lwi, - sbi, shi, swi, msrset, msrclr, tuqula, fadd, frsub, fmul, fdiv, + sb, sbea, sbr, sh, shea, shr, sw, swea, swr, swx, lbui, lhui, lwi, lli, + sbi, shi, sli, swi, msrset, msrclr, tuqula, fadd, frsub, fmul, fdiv, fcmp_lt, fcmp_eq, fcmp_le, fcmp_gt, fcmp_ne, fcmp_ge, fcmp_un, flt, fint, fsqrt, tget, tcget, tnget, tncget, tput, tcput, tnput, tncput, -- 2.7.4