S/390: Fix 16 bit pc relative relocs.
authorAndreas Krebbel <krebbel@linux.vnet.ibm.com>
Fri, 4 Nov 2016 18:48:35 +0000 (19:48 +0100)
committerAndreas Krebbel <krebbel@linux.vnet.ibm.com>
Fri, 4 Nov 2016 19:18:35 +0000 (20:18 +0100)
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.

gas/config/tc-s390.c
gas/testsuite/gas/s390/zarch-zEC12.d
gas/testsuite/gas/s390/zarch-zEC12.s

index bc318ee54c5d6a24423d06e712fc304c63019d94..d8a4f92aa8c237aec59911373a47683007899cea 100644 (file)
@@ -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;
index 2989ddab8c4c790928bb5b5d852b95ce0d8bc529..a4be510d3a2c0073f14007a7295de203145f6f2a 100644 (file)
@@ -54,9 +54,16 @@ Disassembly of section .text:
 .*:    b2 e8 c0 56 [    ]*ppa  %r5,%r6,12
 .*:    b9 8f 60 59 [    ]*crdte        %r5,%r6,%r9
 .*:    b9 8f 61 59 [    ]*crdte        %r5,%r6,%r9,1
-.*:    c5 a0 06 00 00 06 [      ]*bprp 10,11e <bar>,11e <bar>
+.*:    c5 a0 0c 00 00 0c [      ]*bprp 10,12a <bar>,12a <bar>
 .*:    c5 a0 00 00 00 00 [      ]*bprp 10,118 <foo\+0x118>,118 <foo\+0x118>
 [       ]*119: R_390_PLT12DBL  bar\+0x1
 [       ]*11b: R_390_PLT24DBL  bar\+0x3
-.* <bar>:
-.*:    07 07 [         ]*nopr  %r7
+.*:    c7 a0 00 00 00 00 [      ]*bpp  10,11e <foo\+0x11e>,0
+[       ]*122: R_390_PLT16DBL  bar\+0x4
+.*:    c7 a0 00 00 00 00 [      ]*bpp  10,124 <foo\+0x124>,0
+[       ]*128: R_390_PC16DBL   baz\+0x4
+
+
+000000000000012a <bar>:
+
+.*:    07 07 [  ]*nopr %r7
index 98f0fdedeb106cba9381cf51e04c98519da20a2f..4754b2089c5046ffbb0f9eead3f8db71e856da81 100644 (file)
@@ -55,4 +55,7 @@ foo:
 
        bprp    10,bar,bar
        bprp    10,bar@PLT,bar@PLT
+
+       bpp     10,bar@PLT,0
+       bpp     10,baz,0
 bar: