case R_SPARC_GOT10:
              case R_SPARC_GOT13:
              case R_SPARC_GOT22:
-             case R_SPARC_GOTDATA_HIX22:
-             case R_SPARC_GOTDATA_LOX10:
              case R_SPARC_GOTDATA_OP_HIX22:
              case R_SPARC_GOTDATA_OP_LOX10:
                tls_type = GOT_NORMAL;
                    _bfd_sparc_elf_local_got_tls_type (abfd)
                      = (char *) (local_got_refcounts + symtab_hdr->sh_info);
                  }
-               local_got_refcounts[r_symndx] += 1;
+               switch (r_type)
+                 {
+                 case R_SPARC_GOTDATA_OP_HIX22:
+                 case R_SPARC_GOTDATA_OP_LOX10:
+                   break;
+
+                 default:
+                   local_got_refcounts[r_symndx] += 1;
+                   break;
+                 }
                old_tls_type = _bfd_sparc_elf_local_got_tls_type (abfd) [r_symndx];
              }
 
            }
          else
            {
-             if (local_got_refcounts[r_symndx] > 0)
-               local_got_refcounts[r_symndx]--;
+             switch (r_type)
+               {
+               case R_SPARC_GOTDATA_OP_HIX22:
+               case R_SPARC_GOTDATA_OP_LOX10:
+                 break;
+
+               default:
+                 if (local_got_refcounts[r_symndx] > 0)
+                   local_got_refcounts[r_symndx]--;
+                 break;
+               }
            }
          break;
 
   return address - htab->tls_size - htab->tls_sec->vma;
 }
 
+/* Return the relocation value for a %gdop relocation.  */
+
+static bfd_vma
+gdopoff (struct bfd_link_info *info, bfd_vma address)
+{
+  struct elf_link_hash_table *htab = elf_hash_table (info);
+  bfd_vma got_base;
+
+  got_base = (htab->hgot->root.u.def.value
+             + htab->hgot->root.u.def.section->output_offset
+             + htab->hgot->root.u.def.section->output_section->vma);
+
+  return address - got_base;
+}
+
 /* Relocate a SPARC ELF section.  */
 
 bfd_boolean
 
          switch (r_type)
            {
-           case R_SPARC_GOTDATA_HIX22:
-           case R_SPARC_GOTDATA_LOX10:
+           case R_SPARC_GOTDATA_OP:
+             continue;
+
            case R_SPARC_GOTDATA_OP_HIX22:
            case R_SPARC_GOTDATA_OP_LOX10:
+             r_type = (r_type == R_SPARC_GOTDATA_OP_HIX22
+                       ? R_SPARC_GOT22
+                       : R_SPARC_GOT10);
+             howto = _bfd_sparc_elf_howto_table + r_type;
+             /* Fall through.  */
+
            case R_SPARC_GOT10:
            case R_SPARC_GOT13:
            case R_SPARC_GOT22:
 
       switch (r_type)
        {
-       case R_SPARC_GOTDATA_HIX22:
-       case R_SPARC_GOTDATA_LOX10:
        case R_SPARC_GOTDATA_OP_HIX22:
        case R_SPARC_GOTDATA_OP_LOX10:
-         /* We don't support these code transformation optimizations
-            yet, so just leave the sequence alone and treat as
-            GOT22/GOT10.  */
-         if (r_type == R_SPARC_GOTDATA_HIX22
-             || r_type == R_SPARC_GOTDATA_OP_HIX22)
-           r_type = R_SPARC_GOT22;
+         if (SYMBOL_REFERENCES_LOCAL (info, h))
+           r_type = (r_type == R_SPARC_GOTDATA_OP_HIX22
+                     ? R_SPARC_GOTDATA_HIX22
+                     : R_SPARC_GOTDATA_LOX10);
          else
-           r_type = R_SPARC_GOT10;
-         /* Fall through. */
+           r_type = (r_type == R_SPARC_GOTDATA_OP_HIX22
+                     ? R_SPARC_GOT22
+                     : R_SPARC_GOT10);
+         howto = _bfd_sparc_elf_howto_table + r_type;
+         break;
+
+       case R_SPARC_GOTDATA_OP:
+         if (SYMBOL_REFERENCES_LOCAL (info, h))
+           {
+             bfd_vma insn = bfd_get_32 (input_bfd, contents + rel->r_offset);
+
+             /* {ld,ldx} [%rs1 + %rs2], %rd --> add %rs1, %rs2, %rd */
+             relocation = 0x80000000 | (insn & 0x3e07c01f);
+             bfd_put_32 (output_bfd, relocation, contents + rel->r_offset);
+           }
+         continue;
+       }
+
+      switch (r_type)
+       {
+       case R_SPARC_GOTDATA_HIX22:
+       case R_SPARC_GOTDATA_LOX10:
+         relocation = gdopoff (info, relocation);
+         break;
 
        case R_SPARC_GOT10:
        case R_SPARC_GOT13:
            }
          continue;
 
-       case R_SPARC_GOTDATA_OP:
-         /* We don't support gotdata code transformation optimizations
-            yet, so simply leave the sequence as-is.  */
-         continue;
-
        case R_SPARC_TLS_IE_LD:
        case R_SPARC_TLS_IE_LDX:
          if (! info->shared && (h == NULL || h->dynindx == -1))
 
          r = bfd_reloc_ok;
        }
-      else if (r_type == R_SPARC_HIX22)
+      else if (r_type == R_SPARC_HIX22
+              || r_type == R_SPARC_GOTDATA_HIX22)
        {
          bfd_vma x;
 
          relocation += rel->r_addend;
-         relocation = relocation ^ MINUS_ONE;
+         if (r_type == R_SPARC_HIX22
+             || (bfd_signed_vma) relocation < 0)
+           relocation = relocation ^ MINUS_ONE;
 
          x = bfd_get_32 (input_bfd, contents + rel->r_offset);
          x = (x & ~(bfd_vma) 0x3fffff) | ((relocation >> 10) & 0x3fffff);
                                  bfd_arch_bits_per_address (input_bfd),
                                  relocation);
        }
-      else if (r_type == R_SPARC_LOX10)
+      else if (r_type == R_SPARC_LOX10
+              || r_type == R_SPARC_GOTDATA_LOX10)
        {
          bfd_vma x;
 
          relocation += rel->r_addend;
-         relocation = (relocation & 0x3ff) | 0x1c00;
+         if (r_type == R_SPARC_LOX10
+             || (bfd_signed_vma) relocation < 0)
+           relocation = (relocation & 0x3ff) | 0x1c00;
+         else
+           relocation = (relocation & 0x3ff);
 
          x = bfd_get_32 (input_bfd, contents + rel->r_offset);
          x = (x & ~(bfd_vma) 0x1fff) | relocation;
 
  +1010:        7f ff ff fc     call  1000 <_.*>
  +1014:        ae 05 e0 d0     add  %l7, 0xd0, %l7     ! 1010d0 <.*>
  +1018:        01 00 00 00     nop *
- +101c:        23 00 00 08     sethi  %hi\(0x2000\), %l1
+ +101c:        23 00 00 00     sethi  %hi\(0\), %l1
  +1020:        01 00 00 00     nop *
  +1024:        a2 1c 60 08     xor  %l1, 8, %l1
  +1028:        01 00 00 00     nop *
  +102c:        f0 5d c0 11     ldx  \[ %l7 \+ %l1 \], %i0
  +1030:        01 00 00 00     nop *
- +1034:        81 c7 e0 08     ret 
- +1038:        81 e8 00 00     restore 
+ +1034:        23 00 00 03     sethi  %hi\(0xc00\), %l1
+ +1038:        01 00 00 00     nop *
+ +103c:        a2 1c 63 24     xor  %l1, 0x324, %l1
+ +1040:        01 00 00 00     nop *
+ +1044:        b0 05 c0 11     add  %l7, %l1, %i0
+ +1048:        01 00 00 00     nop *
+ +104c:        81 c7 e0 08     ret 
+ +1050:        81 e8 00 00     restore 
 #pass