diff options
author | Andreas Krebbel <krebbel@linux.vnet.ibm.com> | 2016-11-04 19:48:35 +0100 |
---|---|---|
committer | Andreas Krebbel <krebbel@linux.vnet.ibm.com> | 2016-11-04 20:18:35 +0100 |
commit | feb4bea70a297eb6316d1b0685bbbb8095b7fb29 (patch) | |
tree | daedaaa9da0e911fd4238f90ce875559a4b8beb5 /gas/config/tc-s390.c | |
parent | d46a21655318492db1e6113972fb02ab49eae75f (diff) | |
download | gdb-feb4bea70a297eb6316d1b0685bbbb8095b7fb29.zip gdb-feb4bea70a297eb6316d1b0685bbbb8095b7fb29.tar.gz gdb-feb4bea70a297eb6316d1b0685bbbb8095b7fb29.tar.bz2 |
S/390: Fix 16 bit pc relative relocs.
Since the bpp instruction has been added the 16 bit wide pc relative
relocs might occur at offset 2 as well at offset 4 in an instruction.
With this patch the different adjustment is passed from
md_gather_operand to md_apply_fix via fx_pcrel_adjust field in the fix
data structure.
No regressions on s390x.
gas/ChangeLog:
2016-11-04 Andreas Krebbel <krebbel@linux.vnet.ibm.com>
* config/tc-s390.c (md_gather_operands): Set fx_pcrel_adjust.
(md_apply_fix): Use/Set fx_pcrel_adjust.
* testsuite/gas/s390/zarch-zEC12.d: Add bpp reloc test pattern.
* testsuite/gas/s390/zarch-zEC12.s: Add bpp reloc test.
Diffstat (limited to 'gas/config/tc-s390.c')
-rw-r--r-- | gas/config/tc-s390.c | 24 |
1 files changed, 20 insertions, 4 deletions
diff --git a/gas/config/tc-s390.c b/gas/config/tc-s390.c index bc318ee..d8a4f92a 100644 --- a/gas/config/tc-s390.c +++ b/gas/config/tc-s390.c @@ -1652,6 +1652,9 @@ md_gather_operands (char *str, || fixups[i].reloc == BFD_RELOC_390_GOT20 || fixups[i].reloc == BFD_RELOC_390_GOT16) fixP->fx_no_overflow = 1; + + if (operand->flags & S390_OPERAND_PCREL) + fixP->fx_pcrel_adjust = operand->shift / 8; } else fix_new_exp (frag_now, f - frag_now->fr_literal, 4, &fixups[i].exp, @@ -2306,6 +2309,7 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED) fixP->fx_size = 2; fixP->fx_where += 1; fixP->fx_offset += 1; + fixP->fx_pcrel_adjust = 1; fixP->fx_r_type = BFD_RELOC_390_PC12DBL; } else if (operand->bits == 16 && operand->shift == 16) @@ -2316,16 +2320,27 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED) { fixP->fx_r_type = BFD_RELOC_390_PC16DBL; fixP->fx_offset += 2; + fixP->fx_pcrel_adjust = 2; } else fixP->fx_r_type = BFD_RELOC_16; } + else if (operand->bits == 16 && operand->shift == 32 + && (operand->flags & S390_OPERAND_PCREL)) + { + fixP->fx_size = 2; + fixP->fx_where += 4; + fixP->fx_offset += 4; + fixP->fx_pcrel_adjust = 4; + fixP->fx_r_type = BFD_RELOC_390_PC16DBL; + } else if (operand->bits == 24 && operand->shift == 24 && (operand->flags & S390_OPERAND_PCREL)) { fixP->fx_size = 3; fixP->fx_where += 3; fixP->fx_offset += 3; + fixP->fx_pcrel_adjust = 3; fixP->fx_r_type = BFD_RELOC_390_PC24DBL; } else if (operand->bits == 32 && operand->shift == 16 @@ -2334,6 +2349,7 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED) fixP->fx_size = 4; fixP->fx_where += 2; fixP->fx_offset += 2; + fixP->fx_pcrel_adjust = 2; fixP->fx_r_type = BFD_RELOC_390_PC32DBL; } else @@ -2369,7 +2385,7 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED) case BFD_RELOC_390_PC12DBL: case BFD_RELOC_390_PLT12DBL: if (fixP->fx_pcrel) - value++; + value += fixP->fx_pcrel_adjust; if (fixP->fx_done) { @@ -2420,14 +2436,14 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED) break; case BFD_RELOC_390_PC16DBL: case BFD_RELOC_390_PLT16DBL: - value += 2; + value += fixP->fx_pcrel_adjust; if (fixP->fx_done) md_number_to_chars (where, (offsetT) value >> 1, 2); break; case BFD_RELOC_390_PC24DBL: case BFD_RELOC_390_PLT24DBL: - value += 3; + value += fixP->fx_pcrel_adjust; if (fixP->fx_done) { unsigned int mop; @@ -2465,7 +2481,7 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED) case BFD_RELOC_390_GOTPCDBL: case BFD_RELOC_390_GOTENT: case BFD_RELOC_390_GOTPLTENT: - value += 2; + value += fixP->fx_pcrel_adjust; if (fixP->fx_done) md_number_to_chars (where, (offsetT) value >> 1, 4); break; |