diff options
Diffstat (limited to 'gas')
-rw-r--r-- | gas/ChangeLog | 20 | ||||
-rw-r--r-- | gas/config/tc-mips.c | 85 | ||||
-rw-r--r-- | gas/testsuite/ChangeLog | 7 | ||||
-rw-r--r-- | gas/testsuite/gas/mips/elf-rel13-mips16.d | 17 | ||||
-rw-r--r-- | gas/testsuite/gas/mips/elf-rel13-mips16.s | 24 | ||||
-rw-r--r-- | gas/testsuite/gas/mips/elf-rel8-mips16.d | 38 | ||||
-rw-r--r-- | gas/testsuite/gas/mips/elf-rel8-mips16.s | 39 | ||||
-rw-r--r-- | gas/testsuite/gas/mips/elf-rel9-mips16.d | 70 | ||||
-rw-r--r-- | gas/testsuite/gas/mips/elf-rel9-mips16.s | 59 | ||||
-rw-r--r-- | gas/testsuite/gas/mips/mips.exp | 3 |
10 files changed, 342 insertions, 20 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog index 6f03d92..11a0d24 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,23 @@ +2008-08-06 Richard Sandiford <rdsandiford@googlemail.com> + + * config/tc-mips.c (mips16_reloc_p, got16_reloc_p, hi16_reloc_p) + (lo16_reloc_p): New functions. + (reloc_needs_lo_p): Use hi16_reloc_p and got16_reloc_p to + generalize relocation checks. + (matching_lo_reloc): New function. + (fixup_has_matching_lo_p): Use it. + (mips16_mark_labels): Don't clobber a symbol's visibility. + (append_insn): Use hi16_reloc_p and lo16_reloc_p. + (mips16_ip): Handle BFD_RELOC_MIPS16_GOT16 and BFD_RELOC_MIPS16_CALL16. + (md_apply_fix): Likewise. + (mips16_percent_op): Add %got and %call16. + (mips_frob_file): Use got16_reloc_p to generalize relocation checks. + Use matching_lo_reloc. + (mips_force_relocation): Use hi16_reloc_p and lo16_reloc_p to + generalize relocation checks. + (mips_fix_adjustable): Use lo16_reloc_p to generalize relocation + checks. + 2008-08-06 DJ Delorie <dj@redhat.com> * NEWS: Mention these changes. diff --git a/gas/config/tc-mips.c b/gas/config/tc-mips.c index 1e2adc3..c03cca2 100644 --- a/gas/config/tc-mips.c +++ b/gas/config/tc-mips.c @@ -2129,6 +2129,46 @@ md_assemble (char *str) } } +/* Convenience functions for abstracting away the differences between + MIPS16 and non-MIPS16 relocations. */ + +static inline bfd_boolean +mips16_reloc_p (bfd_reloc_code_real_type reloc) +{ + switch (reloc) + { + case BFD_RELOC_MIPS16_JMP: + case BFD_RELOC_MIPS16_GPREL: + case BFD_RELOC_MIPS16_GOT16: + case BFD_RELOC_MIPS16_CALL16: + case BFD_RELOC_MIPS16_HI16_S: + case BFD_RELOC_MIPS16_HI16: + case BFD_RELOC_MIPS16_LO16: + return TRUE; + + default: + return FALSE; + } +} + +static inline bfd_boolean +got16_reloc_p (bfd_reloc_code_real_type reloc) +{ + return reloc == BFD_RELOC_MIPS_GOT16 || reloc == BFD_RELOC_MIPS16_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; +} + +static inline bfd_boolean +lo16_reloc_p (bfd_reloc_code_real_type reloc) +{ + return reloc == BFD_RELOC_LO16 || reloc == BFD_RELOC_MIPS16_LO16; +} + /* Return true if the given relocation might need a matching %lo(). This is only "might" because SVR4 R_MIPS_GOT16 relocations only need a matching %lo() when applied to local symbols. */ @@ -2137,11 +2177,19 @@ static inline bfd_boolean reloc_needs_lo_p (bfd_reloc_code_real_type reloc) { return (HAVE_IN_PLACE_ADDENDS - && (reloc == BFD_RELOC_HI16_S - || reloc == BFD_RELOC_MIPS16_HI16_S + && (hi16_reloc_p (reloc) /* VxWorks R_MIPS_GOT16 relocs never need a matching %lo(); all GOT16 relocations evaluate to "G". */ - || (reloc == BFD_RELOC_MIPS_GOT16 && mips_pic != VXWORKS_PIC))); + || (got16_reloc_p (reloc) && mips_pic != VXWORKS_PIC))); +} + +/* Return the type of %lo() reloc needed by RELOC, given that + reloc_needs_lo_p. */ + +static inline bfd_reloc_code_real_type +matching_lo_reloc (bfd_reloc_code_real_type reloc) +{ + return mips16_reloc_p (reloc) ? BFD_RELOC_MIPS16_LO16 : BFD_RELOC_LO16; } /* Return true if the given fixup is followed by a matching R_MIPS_LO16 @@ -2151,8 +2199,7 @@ static inline bfd_boolean fixup_has_matching_lo_p (fixS *fixp) { return (fixp->fx_next != NULL - && (fixp->fx_next->fx_r_type == BFD_RELOC_LO16 - || fixp->fx_next->fx_r_type == BFD_RELOC_MIPS16_LO16) + && fixp->fx_next->fx_r_type == matching_lo_reloc (fixp->fx_r_type) && fixp->fx_addsy == fixp->fx_next->fx_addsy && fixp->fx_offset == fixp->fx_next->fx_offset); } @@ -2934,8 +2981,6 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr, && (reloc_type[0] == BFD_RELOC_16 || reloc_type[0] == BFD_RELOC_32 || reloc_type[0] == BFD_RELOC_MIPS_JMP - || reloc_type[0] == BFD_RELOC_HI16_S - || reloc_type[0] == BFD_RELOC_LO16 || reloc_type[0] == BFD_RELOC_GPREL16 || reloc_type[0] == BFD_RELOC_MIPS_LITERAL || reloc_type[0] == BFD_RELOC_GPREL32 @@ -2948,8 +2993,8 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr, || reloc_type[0] == BFD_RELOC_MIPS_REL16 || reloc_type[0] == BFD_RELOC_MIPS_RELGOT || reloc_type[0] == BFD_RELOC_MIPS16_GPREL - || reloc_type[0] == BFD_RELOC_MIPS16_HI16_S - || reloc_type[0] == BFD_RELOC_MIPS16_LO16)) + || hi16_reloc_p (reloc_type[0]) + || lo16_reloc_p (reloc_type[0]))) ip->fixp[0]->fx_no_overflow = 1; if (mips_relax.sequence) @@ -10092,6 +10137,8 @@ mips16_ip (char *str, struct mips_cl_insn *ip) /* Stuff the immediate value in now, if we can. */ if (imm_expr.X_op == O_constant && *imm_reloc > BFD_RELOC_UNUSED + && *imm_reloc != BFD_RELOC_MIPS16_GOT16 + && *imm_reloc != BFD_RELOC_MIPS16_CALL16 && insn->pinfo != INSN_MACRO) { valueT tmp; @@ -10861,6 +10908,8 @@ static const struct percent_op_match mips16_percent_op[] = { {"%lo", BFD_RELOC_MIPS16_LO16}, {"%gprel", BFD_RELOC_MIPS16_GPREL}, + {"%got", BFD_RELOC_MIPS16_GOT16}, + {"%call16", BFD_RELOC_MIPS16_CALL16}, {"%hi", BFD_RELOC_MIPS16_HI16_S} }; @@ -11954,7 +12003,7 @@ mips_frob_file (void) /* If a GOT16 relocation turns out to be against a global symbol, there isn't supposed to be a matching LO. */ - if (l->fixp->fx_r_type == BFD_RELOC_MIPS_GOT16 + if (got16_reloc_p (l->fixp->fx_r_type) && !pic_need_relax (l->fixp->fx_addsy, l->seg)) continue; @@ -11972,12 +12021,7 @@ mips_frob_file (void) hi_pos = NULL; lo_pos = NULL; matched_lo_p = FALSE; - - if (l->fixp->fx_r_type == BFD_RELOC_MIPS16_HI16 - || l->fixp->fx_r_type == BFD_RELOC_MIPS16_HI16_S) - looking_for_rtype = BFD_RELOC_MIPS16_LO16; - else - looking_for_rtype = BFD_RELOC_LO16; + looking_for_rtype = matching_lo_reloc (l->fixp->fx_r_type); for (pos = &seginfo->fix_root; *pos != NULL; pos = &(*pos)->fx_next) { @@ -12030,8 +12074,8 @@ mips_force_relocation (fixS *fixp) if (HAVE_NEWABI && S_GET_SEGMENT (fixp->fx_addsy) == bfd_abs_section_ptr && (fixp->fx_r_type == BFD_RELOC_MIPS_SUB - || fixp->fx_r_type == BFD_RELOC_HI16_S - || fixp->fx_r_type == BFD_RELOC_LO16)) + || hi16_reloc_p (fixp->fx_r_type) + || lo16_reloc_p (fixp->fx_r_type))) return 1; return 0; @@ -12119,6 +12163,8 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED) case BFD_RELOC_MIPS_CALL_HI16: case BFD_RELOC_MIPS_CALL_LO16: case BFD_RELOC_MIPS16_GPREL: + case BFD_RELOC_MIPS16_GOT16: + case BFD_RELOC_MIPS16_CALL16: case BFD_RELOC_MIPS16_HI16: case BFD_RELOC_MIPS16_HI16_S: case BFD_RELOC_MIPS16_JMP: @@ -13926,8 +13972,7 @@ mips_fix_adjustable (fixS *fixp) placed anywhere. Rather than break backwards compatibility by changing this, it seems better not to force the issue, and instead keep the original symbol. This will work with either linker behavior. */ - if ((fixp->fx_r_type == BFD_RELOC_LO16 - || fixp->fx_r_type == BFD_RELOC_MIPS16_LO16 + if ((lo16_reloc_p (fixp->fx_r_type) || reloc_needs_lo_p (fixp->fx_r_type)) && HAVE_IN_PLACE_ADDENDS && (S_GET_SEGMENT (fixp->fx_addsy)->flags & SEC_MERGE) != 0) diff --git a/gas/testsuite/ChangeLog b/gas/testsuite/ChangeLog index 7516f50..e75b7cf 100644 --- a/gas/testsuite/ChangeLog +++ b/gas/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2008-08-06 Richard Sandiford <rdsandiford@googlemail.com> + + * gas/mips/elf-rel8-mips16.d, gas/mips/elf-rel8-mips16.s, + * gas/mips/elf-rel9-mips16.d, gas/mips/elf-rel9-mips16.s, + * gas/mips/elf-rel13-mips16.d, gas/mips/elf-rel13-mips16.s: New tests. + * gas/mips/mips.exp: Run them. + 2008-08-01 Peter Bergner <bergner@vnet.ibm.com> * gas/ppc/power7.d: New. diff --git a/gas/testsuite/gas/mips/elf-rel13-mips16.d b/gas/testsuite/gas/mips/elf-rel13-mips16.d new file mode 100644 index 0000000..aa404ab --- /dev/null +++ b/gas/testsuite/gas/mips/elf-rel13-mips16.d @@ -0,0 +1,17 @@ +#as: -march=mips2 -mabi=32 -KPIC +#readelf: --relocs +#name: MIPS ELF reloc 13 (MIPS16 version) + +Relocation section '\.rel\.text' at offset .* contains 9 entries: + *Offset * Info * Type * Sym\.Value * Sym\. Name +0+0002 * 0+..66 * R_MIPS16_GOT16 * 0+0000 * \.data +0+0016 * 0+..69 * R_MIPS16_LO16 * 0+0000 * \.data +0+0012 * 0+..66 * R_MIPS16_GOT16 * 0+0000 * \.data +0+001a * 0+..69 * R_MIPS16_LO16 * 0+0000 * \.data +# The next two lines could be in either order. +0+000e * 0+..66 * R_MIPS16_GOT16 * 0+0000 * \.rodata +0+000a * 0+..66 * R_MIPS16_GOT16 * 0+0000 * \.rodata +0+001e * 0+..69 * R_MIPS16_LO16 * 0+0000 * \.rodata +0+0006 * 0+..66 * R_MIPS16_GOT16 * 0+0000 * \.bss +0+0022 * 0+..69 * R_MIPS16_LO16 * 0+0000 * \.bss +#pass diff --git a/gas/testsuite/gas/mips/elf-rel13-mips16.s b/gas/testsuite/gas/mips/elf-rel13-mips16.s new file mode 100644 index 0000000..2983f0e --- /dev/null +++ b/gas/testsuite/gas/mips/elf-rel13-mips16.s @@ -0,0 +1,24 @@ + .set mips16 + .ent foo +foo: + move $2,$28 + lw $4,%got(l1)($2) + lw $4,%got(l2)($2) + lw $4,%got(l3)($2) + lw $4,%got(l3)($2) + lw $4,%got(l1+0x400)($2) + addiu $4,%lo(l1) + addiu $4,%lo(l1+0x400) + addiu $4,%lo(l3) + addiu $4,%lo(l2) + .align 5 + .end foo + + .data +l1: .word 1 + + .lcomm l2, 4 + + .rdata + .word 1 +l3: .word 2 diff --git a/gas/testsuite/gas/mips/elf-rel8-mips16.d b/gas/testsuite/gas/mips/elf-rel8-mips16.d new file mode 100644 index 0000000..7c834fa --- /dev/null +++ b/gas/testsuite/gas/mips/elf-rel8-mips16.d @@ -0,0 +1,38 @@ +#as: -march=mips2 -mabi=32 +#objdump: -M gpr-names=numeric -dr +#name: MIPS ELF reloc 8 (MIPS16 version) + +.*: file format .* + +Disassembly of section \.text: + +0+00 <foo>: + 0: 675c move \$2,\$28 + 2: f000 6c00 li \$4,0 + 2: R_MIPS16_HI16 gvar + 6: f400 3480 sll \$4,16 + a: f000 4c00 addiu \$4,0 + a: R_MIPS16_LO16 gvar + e: f000 9d80 lw \$4,0\(\$5\) + e: R_MIPS16_LO16 gvar + 12: f000 9982 lw \$4,2\(\$17\) + 16: f000 9a80 lw \$4,0\(\$2\) + 16: R_MIPS16_GOT16 \.data + 1a: f000 c4a0 sb \$5,0\(\$4\) + 1a: R_MIPS16_LO16 \.data + 1e: f000 9a80 lw \$4,0\(\$2\) + 1e: R_MIPS16_GOT16 \.data + 22: f000 4c00 addiu \$4,0 + 22: R_MIPS16_LO16 \.data + 26: f000 9a60 lw \$3,0\(\$2\) + 26: R_MIPS16_CALL16 gfunc + 2a: f000 4c00 addiu \$4,0 + 2a: R_MIPS16_CALL16 gfunc + 2e: f000 9a80 lw \$4,0\(\$2\) + 2e: R_MIPS16_GPREL gvar + 32: f000 da80 sw \$4,0\(\$2\) + 32: R_MIPS16_GPREL gvar + 36: f000 4c00 addiu \$4,0 + 36: R_MIPS16_GPREL gvar + 3a: 6500 nop +#pass diff --git a/gas/testsuite/gas/mips/elf-rel8-mips16.s b/gas/testsuite/gas/mips/elf-rel8-mips16.s new file mode 100644 index 0000000..0c9eefe --- /dev/null +++ b/gas/testsuite/gas/mips/elf-rel8-mips16.s @@ -0,0 +1,39 @@ + .equ $fprel, 2 + .set mips16 + + .ent foo +foo: + move $2,$gp + + # Test various forms of relocation syntax. + + li $4,(%hi gvar) + sll $4,16 + addiu $4,(%lo (gvar)) + lw $4,%lo gvar($5) + + # Check that registers aren't confused with $ identifiers. + + lw $4,($fprel)($17) + + # Check various forms of paired relocations. + + lw $4,%got(lvar)($2) + sb $5,%lo(lvar)($4) + + lw $4,%got(lvar)($2) + addiu $4,%lo(lvar) + + # Check individual relocations. + + lw $3,%call16(gfunc)($2) + addiu $4,%call16(gfunc) + + lw $4,%gprel(gvar)($2) + sw $4,%gprel(gvar)($2) + addiu $4,%gprel(gvar) + .align 6 + .end foo + + .data +lvar: .word 1,2 diff --git a/gas/testsuite/gas/mips/elf-rel9-mips16.d b/gas/testsuite/gas/mips/elf-rel9-mips16.d new file mode 100644 index 0000000..738c6fd --- /dev/null +++ b/gas/testsuite/gas/mips/elf-rel9-mips16.d @@ -0,0 +1,70 @@ +#as: -march=mips2 -mabi=32 +#objdump: -M gpr-names=numeric -dr +#name: MIPS ELF reloc 9 (MIPS16 version) + +.*: file format .* + +Disassembly of section \.text: + +0+00 <foo>: + 0: 675c move \$2,\$28 + 2: f000 9a80 lw \$4,0\(\$2\) + 2: R_MIPS16_GOT16 \.data + 6: f000 4c10 addiu \$4,16 + 6: R_MIPS16_LO16 \.data + a: f000 9a80 lw \$4,0\(\$2\) + a: R_MIPS16_GOT16 \.data + e: f020 4c00 addiu \$4,32 + e: R_MIPS16_LO16 \.data + 12: f000 9a80 lw \$4,0\(\$2\) + 12: R_MIPS16_GOT16 \.data + 16: f7ef 4c1c addiu \$4,32764 + 16: R_MIPS16_LO16 \.data + 1a: f000 9a81 lw \$4,1\(\$2\) + 1a: R_MIPS16_GOT16 \.data + 1e: f010 4c00 addiu \$4,-32768 + 1e: R_MIPS16_LO16 \.data + 22: f000 9a81 lw \$4,1\(\$2\) + 22: R_MIPS16_GOT16 \.data + 26: f7ff 4c1c addiu \$4,-4 + 26: R_MIPS16_LO16 \.data + 2a: f000 9a81 lw \$4,1\(\$2\) + 2a: R_MIPS16_GOT16 \.data + 2e: f000 4c00 addiu \$4,0 + 2e: R_MIPS16_LO16 \.data + 32: f000 9a82 lw \$4,2\(\$2\) + 32: R_MIPS16_GOT16 \.data + 36: f010 4c10 addiu \$4,-32752 + 36: R_MIPS16_LO16 \.data + 3a: f000 9a82 lw \$4,2\(\$2\) + 3a: R_MIPS16_GOT16 \.data + 3e: f01e 4c00 addiu \$4,-4096 + 3e: R_MIPS16_LO16 \.data + 42: f000 9a82 lw \$4,2\(\$2\) + 42: R_MIPS16_GOT16 \.data + 46: f7ff 4c1f addiu \$4,-1 + 46: R_MIPS16_LO16 \.data + 4a: f000 9a82 lw \$4,2\(\$2\) + 4a: R_MIPS16_GOT16 \.data + 4e: f000 4c00 addiu \$4,0 + 4e: R_MIPS16_LO16 \.data + 52: f000 9a83 lw \$4,3\(\$2\) + 52: R_MIPS16_GOT16 \.data + 56: f342 4c05 addiu \$4,4933 + 56: R_MIPS16_LO16 \.data + 5a: f018 9a80 lw \$4,-16384\(\$2\) + 5a: R_MIPS16_GPREL \.sdata + 5e: f018 9a84 lw \$4,-16380\(\$2\) + 5e: R_MIPS16_GPREL \.sdata + 62: f018 9a84 lw \$4,-16380\(\$2\) + 62: R_MIPS16_GPREL \.sdata + 66: f018 9a88 lw \$4,-16376\(\$2\) + 66: R_MIPS16_GPREL \.sdata + 6a: f018 9a8c lw \$4,-16372\(\$2\) + 6a: R_MIPS16_GPREL \.sdata + 6e: f018 9a94 lw \$4,-16364\(\$2\) + 6e: R_MIPS16_GPREL \.sdata + 72: f018 9a98 lw \$4,-16360\(\$2\) + 72: R_MIPS16_GPREL \.sdata + 76: 6500 nop +#pass diff --git a/gas/testsuite/gas/mips/elf-rel9-mips16.s b/gas/testsuite/gas/mips/elf-rel9-mips16.s new file mode 100644 index 0000000..a4f54ed --- /dev/null +++ b/gas/testsuite/gas/mips/elf-rel9-mips16.s @@ -0,0 +1,59 @@ + .set mips16 + .ent foo +foo: + move $2,$28 + lw $4,%got(l1)($2) + addiu $4,%lo(l1) + + lw $4,%got(l1 + 16)($2) + addiu $4,%lo(l1 + 16) + + lw $4,%got(l1 + 0x7fec)($2) + addiu $4,%lo(l1 + 0x7fec) + + lw $4,%got(l1 + 0x7ff0)($2) + addiu $4,%lo(l1 + 0x7ff0) + + lw $4,%got(l1 + 0xffec)($2) + addiu $4,%lo(l1 + 0xffec) + + lw $4,%got(l1 + 0xfff0)($2) + addiu $4,%lo(l1 + 0xfff0) + + lw $4,%got(l1 + 0x18000)($2) + addiu $4,%lo(l1 + 0x18000) + + lw $4,%got(l2)($2) + addiu $4,%lo(l2) + + lw $4,%got(l2 + 0xfff)($2) + addiu $4,%lo(l2 + 0xfff) + + lw $4,%got(l2 + 0x1000)($2) + addiu $4,%lo(l2 + 0x1000) + + lw $4,%got(l2 + 0x12345)($2) + addiu $4,%lo(l2 + 0x12345) + + lw $4,%gprel(l3)($2) + lw $4,%gprel(l3 + 4)($2) + lw $4,%gprel(l4)($2) + lw $4,%gprel(l4 + 4)($2) + lw $4,%gprel(l5)($2) + lw $4,%gprel(l5 + 8)($2) + lw $4,%gprel(l5 + 12)($2) + + .align 6 + .end foo + + .data + .word 1,2,3,4 +l1: .word 4,5 + .space 0x1f000 - 24 +l2: .word 7,8 + + .sdata +l3: .word 1 +l4: .word 2 + .word 3 +l5: .word 4 diff --git a/gas/testsuite/gas/mips/mips.exp b/gas/testsuite/gas/mips/mips.exp index 16edfb7..3c4a919 100644 --- a/gas/testsuite/gas/mips/mips.exp +++ b/gas/testsuite/gas/mips/mips.exp @@ -653,13 +653,16 @@ if { [istarget mips*-*-vxworks*] } { } run_dump_test "elf-rel7" run_dump_test "elf-rel8" + run_dump_test "elf-rel8-mips16" run_dump_test "elf-rel9" + run_dump_test "elf-rel9-mips16" if $has_newabi { run_dump_test "elf-rel10" run_dump_test "elf-rel11" } run_dump_test "elf-rel12" run_dump_test "elf-rel13" + run_dump_test "elf-rel13-mips16" run_dump_test "elf-rel14" if $has_newabi { |