From 2309ddf22209e1d2ab769dc778d9f764463b8509 Mon Sep 17 00:00:00 2001 From: "Maciej W. Rozycki" Date: Fri, 29 Jul 2011 22:46:29 +0000 Subject: [PATCH] bfd/ * elfxx-mips.c: Adjust comments throughout. (mips_elf_relax_delete_bytes): Reshape code. (_bfd_mips_elf_relax_section): Remove check for R_MICROMIPS_GPREL16 relocations. Reshape code. gas/ * config/tc-mips.c: Adjust comments throughout. (reglist_lookup): Reshape code. (jmp_reloc_p, jalr_reloc_p): Reformat. (got16_reloc_p, hi16_reloc_p, lo16_reloc_p): Handle microMIPS relocations. (gpr_mod_mask): Remove unused variable. (gpr_read_mask, gpr_write_mask): Reshape code. (fpr_read_mask, fpr_write_mask): Likewise. (nops_for_vr4130): Ensure non-microMIPS mode. (can_swap_branch_p): Correct pinfo2 reference. Reshape code. (append_insn): Skip Loongson 2F workaround in MIPS16 mode. Use the outermost operator of a compound relocation to determines the relocated field. Fix formatting. (md_convert_frag): Reshape code. include/opcode/ * mips.h: Clarify the description of microMIPS instruction manipulation macros. (MICROMIPSOP_MASK_MAJOR, MICROMIPSOP_SH_MAJOR): Remove macros. --- bfd/ChangeLog | 7 ++ bfd/elfxx-mips.c | 49 ++++++------- gas/ChangeLog | 17 +++++ gas/config/tc-mips.c | 178 ++++++++++++++++++----------------------------- include/opcode/ChangeLog | 6 ++ include/opcode/mips.h | 9 +-- 6 files changed, 122 insertions(+), 144 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index c3fac58..54d926f 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,10 @@ +2011-07-29 Maciej W. Rozycki + + * elfxx-mips.c: Adjust comments throughout. + (mips_elf_relax_delete_bytes): Reshape code. + (_bfd_mips_elf_relax_section): Remove check for + R_MICROMIPS_GPREL16 relocations. Reshape code. + 2011-07-28 Roland McGrath * elf32-i386.c (NACL_PLT_ENTRY_SIZE, NACLMASK): New macros. diff --git a/bfd/elfxx-mips.c b/bfd/elfxx-mips.c index 53a9477..36b881e 100644 --- a/bfd/elfxx-mips.c +++ b/bfd/elfxx-mips.c @@ -11910,8 +11910,7 @@ mips_elf_relax_delete_bytes (bfd *abfd, symtab_hdr = &elf_tdata (abfd)->symtab_hdr; isym = (Elf_Internal_Sym *) symtab_hdr->contents; for (isymend = isym + symtab_hdr->sh_info; isym < isymend; isym++) - if (isym->st_shndx == sec_shndx - && isym->st_value > addr) + if (isym->st_shndx == sec_shndx && isym->st_value > addr) isym->st_value -= count; /* Now adjust the global symbols defined in this section. */ @@ -11928,9 +11927,8 @@ mips_elf_relax_delete_bytes (bfd *abfd, || sym_hash->root.type == bfd_link_hash_defweak) && sym_hash->root.u.def.section == sec) { - bfd_vma value; + bfd_vma value = sym_hash->root.u.def.value; - value = sym_hash->root.u.def.value; if (ELF_ST_IS_MICROMIPS (sym_hash->other)) value &= MINUS_TWO; if (value > addr) @@ -12336,6 +12334,7 @@ _bfd_mips_elf_relax_section (bfd *abfd, asection *sec, unsigned long opcode; bfd_vma symval; bfd_vma pcrval; + bfd_byte *ptr; int fndopc; /* The number of bytes to delete for relaxation and from where @@ -12347,8 +12346,7 @@ _bfd_mips_elf_relax_section (bfd *abfd, asection *sec, this reloc. */ if (r_type != R_MICROMIPS_HI16 && r_type != R_MICROMIPS_PC16_S1 - && r_type != R_MICROMIPS_26_S1 - && r_type != R_MICROMIPS_GPREL16) + && r_type != R_MICROMIPS_26_S1) continue; /* Get the section contents if we haven't done so already. */ @@ -12361,6 +12359,7 @@ _bfd_mips_elf_relax_section (bfd *abfd, asection *sec, else if (!bfd_malloc_and_get_section (abfd, sec, &contents)) goto error_return; } + ptr = contents + irel->r_offset; /* Read this BFD's local symbols if we haven't done so already. */ if (isymbuf == NULL && symtab_hdr->sh_info != 0) @@ -12432,8 +12431,8 @@ _bfd_mips_elf_relax_section (bfd *abfd, asection *sec, if (irel->r_offset + 4 > sec->size) continue; - opcode = bfd_get_16 (abfd, contents + irel->r_offset ) << 16; - opcode |= bfd_get_16 (abfd, contents + irel->r_offset + 2); + opcode = bfd_get_16 (abfd, ptr ) << 16; + opcode |= bfd_get_16 (abfd, ptr + 2); /* This is the pc-relative distance from the instruction the relocation is applied to, to the symbol referred. */ @@ -12477,7 +12476,7 @@ _bfd_mips_elf_relax_section (bfd *abfd, asection *sec, /* See if the LUI instruction *might* be in a branch delay slot. */ if (irel->r_offset >= 2 - && check_br16_dslot (abfd, contents + irel->r_offset - 2) > 0 + && check_br16_dslot (abfd, ptr - 2) && !(irel->r_offset >= 4 /* If the instruction is actually a 4-byte branch, the value of check_br16_dslot doesn't matter. @@ -12487,7 +12486,7 @@ _bfd_mips_elf_relax_section (bfd *abfd, asection *sec, irel->r_offset - 4))) continue; if (irel->r_offset >= 4 - && check_br32_dslot (abfd, contents + irel->r_offset - 4) > 0) + && check_br32_dslot (abfd, ptr - 4)) continue; reg = OP32_SREG (opcode); @@ -12502,11 +12501,11 @@ _bfd_mips_elf_relax_section (bfd *abfd, asection *sec, case 0: break; case 2: - if (check_br16 (abfd, contents + irel->r_offset + 4, reg)) + if (check_br16 (abfd, ptr + 4, reg)) break; continue; case 4: - if (check_br32 (abfd, contents + irel->r_offset + 4, reg)) + if (check_br32 (abfd, ptr + 4, reg)) break; continue; default: @@ -12581,8 +12580,7 @@ _bfd_mips_elf_relax_section (bfd *abfd, asection *sec, && irel->r_offset + 5 < sec->size && ((fndopc = find_match (opcode, bz_rs_insns_32)) >= 0 || (fndopc = find_match (opcode, bz_rt_insns_32)) >= 0) - && MATCH (bfd_get_16 (abfd, contents + irel->r_offset + 4), - nop_insn_16)) + && MATCH (bfd_get_16 (abfd, ptr + 4), nop_insn_16)) { unsigned long reg; @@ -12593,10 +12591,8 @@ _bfd_mips_elf_relax_section (bfd *abfd, asection *sec, | BZC32_REG_FIELD (reg) | (opcode & 0xffff)); /* Addend value. */ - bfd_put_16 (abfd, (opcode >> 16) & 0xffff, - contents + irel->r_offset); - bfd_put_16 (abfd, opcode & 0xffff, - contents + irel->r_offset + 2); + bfd_put_16 (abfd, (opcode >> 16) & 0xffff, ptr); + bfd_put_16 (abfd, opcode & 0xffff, ptr + 2); /* Delete the 16-bit delay slot NOP: two bytes from irel->offset + 4. */ @@ -12617,7 +12613,7 @@ _bfd_mips_elf_relax_section (bfd *abfd, asection *sec, bfd_put_16 (abfd, (b_insn_16.match | (opcode & 0x3ff)), /* Addend value. */ - contents + irel->r_offset); + ptr); /* Delete 2 bytes from irel->r_offset + 2. */ delcnt = 2; @@ -12645,7 +12641,7 @@ _bfd_mips_elf_relax_section (bfd *abfd, asection *sec, (bz_insns_16[fndopc].match | BZ16_REG_FIELD (reg) | (opcode & 0x7f)), /* Addend value. */ - contents + irel->r_offset); + ptr); /* Delete 2 bytes from irel->r_offset + 2. */ delcnt = 2; @@ -12661,14 +12657,13 @@ _bfd_mips_elf_relax_section (bfd *abfd, asection *sec, unsigned long n32opc; bfd_boolean relaxed = FALSE; - n32opc = bfd_get_16 (abfd, contents + irel->r_offset + 4) << 16; - n32opc |= bfd_get_16 (abfd, contents + irel->r_offset + 6); + n32opc = bfd_get_16 (abfd, ptr + 4) << 16; + n32opc |= bfd_get_16 (abfd, ptr + 6); if (MATCH (n32opc, nop_insn_32)) { /* Replace delay slot 32-bit NOP with a 16-bit NOP. */ - bfd_put_16 (abfd, nop_insn_16.match, - contents + irel->r_offset + 4); + bfd_put_16 (abfd, nop_insn_16.match, ptr + 4); relaxed = TRUE; } @@ -12679,7 +12674,7 @@ _bfd_mips_elf_relax_section (bfd *abfd, asection *sec, (move_insn_16.match | MOVE16_RD_FIELD (MOVE32_RD (n32opc)) | MOVE16_RS_FIELD (MOVE32_RS (n32opc))), - contents + irel->r_offset + 4); + ptr + 4); relaxed = TRUE; } @@ -12691,9 +12686,9 @@ _bfd_mips_elf_relax_section (bfd *abfd, asection *sec, /* JAL with 32-bit delay slot that is changed to a JALS with 16-bit delay slot. */ bfd_put_16 (abfd, (jal_insn_32_bd16.match >> 16) & 0xffff, - contents + irel->r_offset); + ptr); bfd_put_16 (abfd, jal_insn_32_bd16.match & 0xffff, - contents + irel->r_offset + 2); + ptr + 2); /* Delete 2 bytes from irel->r_offset + 6. */ delcnt = 2; diff --git a/gas/ChangeLog b/gas/ChangeLog index e91a35a..25e0b62 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,20 @@ +2011-07-29 Maciej W. Rozycki + + * config/tc-mips.c: Adjust comments throughout. + (reglist_lookup): Reshape code. + (jmp_reloc_p, jalr_reloc_p): Reformat. + (got16_reloc_p, hi16_reloc_p, lo16_reloc_p): Handle microMIPS + relocations. + (gpr_mod_mask): Remove unused variable. + (gpr_read_mask, gpr_write_mask): Reshape code. + (fpr_read_mask, fpr_write_mask): Likewise. + (nops_for_vr4130): Ensure non-microMIPS mode. + (can_swap_branch_p): Correct pinfo2 reference. Reshape code. + (append_insn): Skip Loongson 2F workaround in MIPS16 mode. Use + the outermost operator of a compound relocation to determines + the relocated field. Fix formatting. + (md_convert_frag): Reshape code. + 2011-07-29 Tristan Gingold * frags.c (frag_var_init): New function. diff --git a/gas/config/tc-mips.c b/gas/config/tc-mips.c index af78329..8f57985 100644 --- a/gas/config/tc-mips.c +++ b/gas/config/tc-mips.c @@ -483,7 +483,7 @@ static int mips_32bitmode = 0; (strncmp (TARGET_CPU, "mips16", sizeof ("mips16") - 1) == 0 \ || strncmp (TARGET_CANONICAL, "mips-lsi-elf", sizeof ("mips-lsi-elf") - 1) == 0) -/* Return true if the given CPU supports microMIPS. */ +/* Return true if the given CPU supports the microMIPS ASE. */ #define CPU_HAS_MICROMIPS(cpu) 0 /* True if CPU has a dror instruction. */ @@ -2141,7 +2141,7 @@ reg_lookup (char **s, unsigned int types, unsigned int *regnop) As a special exception if one of s0-s7 registers is specified as the range's lower delimiter and s8 (fp) is its upper one, then no registers whose numbers place them between s7 and s8 (i.e. $24-$29) - are selected; they have to be named separately if needed. */ + are selected; they have to be listed separately if needed. */ static int reglist_lookup (char **s, unsigned int types, unsigned int *reglistp) @@ -2150,9 +2150,9 @@ reglist_lookup (char **s, unsigned int types, unsigned int *reglistp) unsigned int lastregno; bfd_boolean ok = TRUE; unsigned int regmask; - unsigned int regno; + char *s_endlist = *s; char *s_reset = *s; - char *s_end_of_list = *s; + unsigned int regno; while (reg_lookup (s, types, ®no)) { @@ -2177,14 +2177,14 @@ reglist_lookup (char **s, unsigned int types, unsigned int *reglistp) regmask ^= (1 << regno) - 1; reglist |= regmask; - s_end_of_list = *s; + s_endlist = *s; if (**s != ',') break; (*s)++; } if (ok) - *s = s_end_of_list; + *s = s_endlist; else *s = s_reset; if (reglistp) @@ -2663,41 +2663,36 @@ micromips_reloc_p (bfd_reloc_code_real_type reloc) } static inline bfd_boolean +jmp_reloc_p (bfd_reloc_code_real_type reloc) +{ + return reloc == BFD_RELOC_MIPS_JMP || reloc == BFD_RELOC_MICROMIPS_JMP; +} + +static inline bfd_boolean got16_reloc_p (bfd_reloc_code_real_type reloc) { - return (reloc == BFD_RELOC_MIPS_GOT16 - || reloc == BFD_RELOC_MIPS16_GOT16 + return (reloc == BFD_RELOC_MIPS_GOT16 || reloc == BFD_RELOC_MIPS16_GOT16 || reloc == BFD_RELOC_MICROMIPS_GOT16); } static inline bfd_boolean hi16_reloc_p (bfd_reloc_code_real_type reloc) { - return (reloc == BFD_RELOC_HI16_S - || reloc == BFD_RELOC_MIPS16_HI16_S + return (reloc == BFD_RELOC_HI16_S || reloc == BFD_RELOC_MIPS16_HI16_S || reloc == BFD_RELOC_MICROMIPS_HI16_S); } static inline bfd_boolean lo16_reloc_p (bfd_reloc_code_real_type reloc) { - return (reloc == BFD_RELOC_LO16 - || reloc == BFD_RELOC_MIPS16_LO16 + return (reloc == BFD_RELOC_LO16 || reloc == BFD_RELOC_MIPS16_LO16 || reloc == BFD_RELOC_MICROMIPS_LO16); } static inline bfd_boolean -jmp_reloc_p (bfd_reloc_code_real_type reloc) -{ - return (reloc == BFD_RELOC_MIPS_JMP - || reloc == BFD_RELOC_MICROMIPS_JMP); -} - -static inline bfd_boolean jalr_reloc_p (bfd_reloc_code_real_type reloc) { - return (reloc == BFD_RELOC_MIPS_JALR - || reloc == BFD_RELOC_MICROMIPS_JALR); + return reloc == BFD_RELOC_MIPS_JALR || reloc == BFD_RELOC_MICROMIPS_JALR; } /* Return true if the given relocation might need a matching %lo(). @@ -2893,17 +2888,15 @@ relax_end (void) mips_relax.sequence = 0; } -/* Return the mask of core registers that instruction IP may - read or write. */ +/* Return the mask of core registers that IP reads or writes. */ static unsigned int gpr_mod_mask (const struct mips_cl_insn *ip) { - unsigned long pinfo, pinfo2; + unsigned long pinfo2; unsigned int mask; mask = 0; - pinfo = ip->insn_mo->pinfo; pinfo2 = ip->insn_mo->pinfo2; if (mips_opts.micromips) { @@ -2969,27 +2962,20 @@ gpr_read_mask (const struct mips_cl_insn *ip) if (pinfo & MIPS16_INSN_READ_GPR_X) mask |= 1 << MIPS16_EXTRACT_OPERAND (REGR32, *ip); } - else if (mips_opts.micromips) - { - if (pinfo & INSN_READ_GPR_T) - mask |= 1 << EXTRACT_OPERAND (1, RT, *ip); - if (pinfo & INSN_READ_GPR_S) - mask |= 1 << EXTRACT_OPERAND (1, RS, *ip); - if (pinfo2 & INSN2_READ_GPR_31) - mask |= 1 << RA; - if (pinfo2 & INSN2_READ_GP) - mask |= 1 << GP; - } else { if (pinfo2 & INSN2_READ_GPR_D) - mask |= 1 << EXTRACT_OPERAND (0, RD, *ip); + mask |= 1 << EXTRACT_OPERAND (mips_opts.micromips, RD, *ip); if (pinfo & INSN_READ_GPR_T) - mask |= 1 << EXTRACT_OPERAND (0, RT, *ip); + mask |= 1 << EXTRACT_OPERAND (mips_opts.micromips, RT, *ip); if (pinfo & INSN_READ_GPR_S) - mask |= 1 << EXTRACT_OPERAND (0, RS, *ip); + mask |= 1 << EXTRACT_OPERAND (mips_opts.micromips, RS, *ip); + if (pinfo2 & INSN2_READ_GP) + mask |= 1 << GP; + if (pinfo2 & INSN2_READ_GPR_31) + mask |= 1 << RA; if (pinfo2 & INSN2_READ_GPR_Z) - mask |= 1 << EXTRACT_OPERAND (0, RZ, *ip); + mask |= 1 << EXTRACT_OPERAND (mips_opts.micromips, RZ, *ip); } /* Don't include register 0. */ return mask & ~1; @@ -3023,23 +3009,14 @@ gpr_write_mask (const struct mips_cl_insn *ip) if (pinfo & MIPS16_INSN_WRITE_GPR_Y) mask |= 1 << MIPS16OP_EXTRACT_REG32R (ip->insn_opcode); } - else if (mips_opts.micromips) - { - if (pinfo & INSN_WRITE_GPR_D) - mask |= 1 << EXTRACT_OPERAND (1, RD, *ip); - if (pinfo & INSN_WRITE_GPR_T) - mask |= 1 << EXTRACT_OPERAND (1, RT, *ip); - if (pinfo2 & INSN2_WRITE_GPR_S) - mask |= 1 << EXTRACT_OPERAND (1, RS, *ip); - if (pinfo & INSN_WRITE_GPR_31) - mask |= 1 << RA; - } else { if (pinfo & INSN_WRITE_GPR_D) mask |= 1 << EXTRACT_OPERAND (mips_opts.micromips, RD, *ip); if (pinfo & INSN_WRITE_GPR_T) mask |= 1 << EXTRACT_OPERAND (mips_opts.micromips, RT, *ip); + if (pinfo2 & INSN2_WRITE_GPR_S) + mask |= 1 << EXTRACT_OPERAND (mips_opts.micromips, RS, *ip); if (pinfo & INSN_WRITE_GPR_31) mask |= 1 << RA; if (pinfo2 & INSN2_WRITE_GPR_Z) @@ -3060,19 +3037,10 @@ fpr_read_mask (const struct mips_cl_insn *ip) mask = 0; pinfo = ip->insn_mo->pinfo; pinfo2 = ip->insn_mo->pinfo2; - if (mips_opts.micromips) + if (!mips_opts.mips16) { if (pinfo2 & INSN2_READ_FPR_D) - mask |= 1 << EXTRACT_OPERAND (1, FD, *ip); - if (pinfo & INSN_READ_FPR_S) - mask |= 1 << EXTRACT_OPERAND (1, FS, *ip); - if (pinfo & INSN_READ_FPR_T) - mask |= 1 << EXTRACT_OPERAND (1, FT, *ip); - if (pinfo & INSN_READ_FPR_R) - mask |= 1 << EXTRACT_OPERAND (1, FR, *ip); - } - else if (!mips_opts.mips16) - { + mask |= 1 << EXTRACT_OPERAND (mips_opts.micromips, FD, *ip); if (pinfo & INSN_READ_FPR_S) mask |= 1 << EXTRACT_OPERAND (mips_opts.micromips, FS, *ip); if (pinfo & INSN_READ_FPR_T) @@ -3100,16 +3068,7 @@ fpr_write_mask (const struct mips_cl_insn *ip) mask = 0; pinfo = ip->insn_mo->pinfo; pinfo2 = ip->insn_mo->pinfo2; - if (mips_opts.micromips) - { - if (pinfo2 & INSN_WRITE_FPR_D) - mask |= 1 << EXTRACT_OPERAND (1, FD, *ip); - if (pinfo & INSN_WRITE_FPR_S) - mask |= 1 << EXTRACT_OPERAND (1, FS, *ip); - if (pinfo & INSN_WRITE_FPR_T) - mask |= 1 << EXTRACT_OPERAND (1, FT, *ip); - } - else if (!mips_opts.mips16) + if (!mips_opts.mips16) { if (pinfo & INSN_WRITE_FPR_D) mask |= 1 << EXTRACT_OPERAND (mips_opts.micromips, FD, *ip); @@ -3316,6 +3275,7 @@ nops_for_vr4130 (int ignore, const struct mips_cl_insn *hist, if (MF_HILO_INSN (hist[i].insn_mo->pinfo)) { /* Extract the destination register. */ + gas_assert (!mips_opts.micromips); mask = gpr_write_mask (&hist[i]); /* No nops are needed if INSN reads that register. */ @@ -3720,8 +3680,9 @@ can_swap_branch_p (struct mips_cl_insn *ip) return FALSE; /* If the previous instruction is in a variant frag other than this - branch's one, we cannot do the swap. This does not apply to the - mips16, which uses variant frags for different purposes. */ + branch's one, we cannot do the swap. This does not apply to + MIPS16/microMIPS code, which uses variant frags for different + purposes. */ if (!HAVE_CODE_COMPRESSION && history[0].frag && history[0].frag->fr_type == rs_machine_dependent) @@ -3781,17 +3742,16 @@ can_swap_branch_p (struct mips_cl_insn *ip) /* If the previous instruction has an incorrect size for a fixed branch delay slot in microMIPS mode, we cannot swap. */ - if (mips_opts.micromips) - { - pinfo2 = ip->insn_mo->pinfo; - if ((pinfo2 & INSN2_BRANCH_DELAY_16BIT) - && insn_length (history) != 2) - return FALSE; - - if ((pinfo2 & INSN2_BRANCH_DELAY_32BIT) - && insn_length (history) != 4) - return FALSE; - } + pinfo2 = ip->insn_mo->pinfo2; + if (mips_opts.micromips + && (pinfo2 & INSN2_BRANCH_DELAY_16BIT) + && insn_length (history) != 2) + return FALSE; + if (mips_opts.micromips + && (pinfo2 & INSN2_BRANCH_DELAY_32BIT) + && insn_length (history) != 4) + return FALSE; + return TRUE; } @@ -3984,10 +3944,10 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr, { unsigned long prev_pinfo, prev_pinfo2, pinfo, pinfo2; bfd_boolean relaxed_branch = FALSE; - bfd_boolean relax32; enum append_method method; + bfd_boolean relax32; - if (mips_fix_loongson2f && !mips_opts.micromips) + if (mips_fix_loongson2f && !HAVE_CODE_COMPRESSION) fix_loongson2f (ip); mips_mark_labels (); @@ -4192,9 +4152,9 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr, If the instruction produced is a branch that we will swap with the preceding instruction, then we add the displacement by which the branch will be moved backwards. This is more appropriate - and for MIPS16/microMIPS code also prevents a debugger from placing - a breakpoint in the middle of the branch (and corrupting code if - software breakpoints are used). */ + and for MIPS16/microMIPS code also prevents a debugger from + placing a breakpoint in the middle of the branch (and corrupting + code if software breakpoints are used). */ dwarf2_emit_insn ((HAVE_CODE_COMPRESSION ? -1 : 0) + (method == APPEND_SWAP ? insn_length (history) : 0)); #endif @@ -4330,6 +4290,7 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr, if (!ip->complete_p && *reloc_type < BFD_RELOC_UNUSED) { bfd_reloc_code_real_type final_type[3]; + reloc_howto_type *howto0; reloc_howto_type *howto; int i; @@ -4340,7 +4301,8 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr, /* In a compound relocation, it is the final (outermost) operator that determines the relocated field. */ - howto = bfd_reloc_type_lookup (stdoutput, final_type[i - 1]); + howto = howto0 = bfd_reloc_type_lookup (stdoutput, final_type[i - 1]); + if (howto == NULL) { /* To reproduce this failure try assembling gas/testsuites/ @@ -4350,16 +4312,17 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr, final_type[i - 1]); howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_16); } - - howto = bfd_reloc_type_lookup (stdoutput, final_type[0]); + + if (i > 1) + howto0 = bfd_reloc_type_lookup (stdoutput, final_type[0]); ip->fixp[0] = fix_new_exp (ip->frag, ip->where, bfd_get_reloc_size (howto), address_expr, - howto->pc_relative, final_type[0]); + howto0 && howto0->pc_relative, + final_type[0]); /* Tag symbols that have a R_MIPS16_26 relocation against them. */ - if (reloc_type[0] == BFD_RELOC_MIPS16_JMP - && ip->fixp[0]->fx_addsy) + if (final_type[0] == BFD_RELOC_MIPS16_JMP && ip->fixp[0]->fx_addsy) *symbol_get_tc (ip->fixp[0]->fx_addsy) = 1; /* These relocations can have an addend that won't fit in @@ -17800,8 +17763,7 @@ md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, segT asec, fragS *fragp) bfd_boolean compact = RELAX_MICROMIPS_COMPACT (fragp->fr_subtype); bfd_boolean al = RELAX_MICROMIPS_LINK (fragp->fr_subtype); int type = RELAX_MICROMIPS_TYPE (fragp->fr_subtype); - unsigned long jal, jalr, jr; - + bfd_boolean short_ds; unsigned long insn; expressionS exp; fixS *fixp; @@ -17841,7 +17803,7 @@ md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, segT asec, fragS *fragp) return; } - /* Handle 32-bit branches that fit or forced to fit. */ + /* Handle 32-bit branches that fit or are forced to fit. */ if (!RELAX_MICROMIPS_RELAX32 (fragp->fr_subtype) || !RELAX_MICROMIPS_TOOFAR32 (fragp->fr_subtype)) { @@ -17914,18 +17876,8 @@ md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, segT asec, fragS *fragp) as_warn_where (fragp->fr_file, fragp->fr_line, _("Relaxed out-of-range branch into a jump")); - /* Check the short-delay-slot bit. */ - if (al && (insn & 0x02000000) != 0) - { - jal = 0x74000000; /* jals */ - jalr = 0x45e0; /* jalrs */ - } - else - { - jal = 0xf4000000; /* jal */ - jalr = 0x45c0; /* jalr */ - } - jr = compact ? 0x45a0 : 0x4580; /* jr/c */ + /* Set the short-delay-slot bit. */ + short_ds = al && (insn & 0x02000000) != 0; if (!RELAX_MICROMIPS_UNCOND (fragp->fr_subtype)) { @@ -17995,6 +17947,8 @@ md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, segT asec, fragS *fragp) if (mips_pic == NO_PIC) { + unsigned long jal = short_ds ? 0x74000000 : 0xf4000000; /* jal/s */ + /* j/jal/jals R_MICROMIPS_26_S1 */ insn = al ? jal : 0xd4000000; @@ -18019,6 +17973,8 @@ md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, segT asec, fragS *fragp) else { unsigned long at = RELAX_MICROMIPS_AT (fragp->fr_subtype); + unsigned long jalr = short_ds ? 0x45e0 : 0x45c0; /* jalr/s */ + unsigned long jr = compact ? 0x45a0 : 0x4580; /* jr/c */ /* lw/ld $at, ($gp) R_MICROMIPS_GOT16 */ insn = HAVE_64BIT_ADDRESSES ? 0xdc1c0000 : 0xfc1c0000; diff --git a/include/opcode/ChangeLog b/include/opcode/ChangeLog index 3c69275..e7bfecd 100644 --- a/include/opcode/ChangeLog +++ b/include/opcode/ChangeLog @@ -1,3 +1,9 @@ +2011-07-29 Maciej W. Rozycki + + * mips.h: Clarify the description of microMIPS instruction + manipulation macros. + (MICROMIPSOP_MASK_MAJOR, MICROMIPSOP_SH_MAJOR): Remove macros. + 2011-07-24 Chao-ying Fu Maciej W. Rozycki diff --git a/include/opcode/mips.h b/include/opcode/mips.h index ba68331..609a4af 100644 --- a/include/opcode/mips.h +++ b/include/opcode/mips.h @@ -1329,13 +1329,10 @@ extern int bfd_mips_num_opcodes; extern const struct mips_opcode mips16_opcodes[]; extern const int bfd_mips16_num_opcodes; -/* These are the bitmasks and shift counts used for the different - fields in the instruction formats. Other than MAJOR, no masks are - provided for the fixed portions of an instruction, since they are - not needed. */ +/* These are the bit masks and shift counts used for the different fields + in the microMIPS instruction formats. No masks are provided for the + fixed portions of an instruction, since they are not needed. */ -#define MICROMIPSOP_MASK_MAJOR 0x3f -#define MICROMIPSOP_SH_MAJOR 26 #define MICROMIPSOP_MASK_IMMEDIATE 0xffff #define MICROMIPSOP_SH_IMMEDIATE 0 #define MICROMIPSOP_MASK_DELTA 0xffff -- 2.7.4