+static bfd_reloc_status_type
+opru18_reloc (bfd *abfd, arelent *reloc_entry, struct bfd_symbol *symbol,
+ void *data, asection *input_section ATTRIBUTE_UNUSED,
+ bfd *output ATTRIBUTE_UNUSED, char **msg ATTRIBUTE_UNUSED)
+{
+ /* This reloc is used for 18 bit General Operand Addressing Postbyte in the
+ INST opru18 form. This is an 18 bit reloc, but the most significant bit
+ is shifted one place to the left of where it would normally be. See
+ Appendix A.4 of the S12Z reference manual. */
+
+ bfd_size_type octets = (reloc_entry->address
+ * OCTETS_PER_BYTE (abfd, input_section));
+ bfd_vma result = bfd_get_24 (abfd, (unsigned char *) data + octets);
+ bfd_vma val = bfd_asymbol_value (symbol);
+
+ /* Keep the wanted bits and discard the rest. */
+ result &= 0xFA0000;
+
+ val += symbol->section->output_section->vma;
+ val += symbol->section->output_offset;
+
+ /* The lowest 17 bits are copied verbatim. */
+ result |= val & 0x1FFFF;
+
+ /* The 18th bit is put into the 19th position. */
+ result |= (val & 0x020000) << 1;
+
+ bfd_put_24 (abfd, result, (unsigned char *) data + octets);
+
+ return bfd_reloc_ok;
+}
+
+