+#if defined(__powerpc__)
+ case R_PPC_ADDR16_HA:
+ *(unsigned short *)loc = (v + 0x8000) >> 16;
+ break;
+
+ case R_PPC_ADDR16_HI:
+ *(unsigned short *)loc = v >> 16;
+ break;
+
+ case R_PPC_ADDR16_LO:
+ *(unsigned short *)loc = v;
+ break;
+#endif
+
+#if defined(__mips__)
+ case R_MIPS_26:
+ if (v % 4)
+ ret = obj_reloc_dangerous;
+ if ((v & 0xf0000000) != ((dot + 4) & 0xf0000000))
+ ret = obj_reloc_overflow;
+ *loc =
+ (*loc & ~0x03ffffff) | ((*loc + (v >> 2)) &
+ 0x03ffffff);
+ break;
+
+ case R_MIPS_HI16:
+ {
+ struct mips_hi16 *n;
+
+ /* We cannot relocate this one now because we don't know the value
+ of the carry we need to add. Save the information, and let LO16
+ do the actual relocation. */
+ n = (struct mips_hi16 *) xmalloc(sizeof *n);
+ n->addr = loc;
+ n->value = v;
+ n->next = ifile->mips_hi16_list;
+ ifile->mips_hi16_list = n;
+ break;
+ }
+
+ case R_MIPS_LO16:
+ {
+ unsigned long insnlo = *loc;
+ Elf32_Addr val, vallo;
+
+ /* Sign extend the addend we extract from the lo insn. */
+ vallo = ((insnlo & 0xffff) ^ 0x8000) - 0x8000;
+
+ if (ifile->mips_hi16_list != NULL) {
+ struct mips_hi16 *l;
+
+ l = ifile->mips_hi16_list;
+ while (l != NULL) {
+ struct mips_hi16 *next;
+ unsigned long insn;
+
+ /* The value for the HI16 had best be the same. */
+ assert(v == l->value);
+
+ /* Do the HI16 relocation. Note that we actually don't
+ need to know anything about the LO16 itself, except where
+ to find the low 16 bits of the addend needed by the LO16. */
+ insn = *l->addr;
+ val =
+ ((insn & 0xffff) << 16) +
+ vallo;
+ val += v;
+
+ /* Account for the sign extension that will happen in the
+ low bits. */
+ val =
+ ((val >> 16) +
+ ((val & 0x8000) !=
+ 0)) & 0xffff;
+
+ insn = (insn & ~0xffff) | val;
+ *l->addr = insn;
+
+ next = l->next;
+ free(l);
+ l = next;
+ }
+
+ ifile->mips_hi16_list = NULL;
+ }
+
+ /* Ok, we're done with the HI16 relocs. Now deal with the LO16. */
+ val = v + vallo;
+ insnlo = (insnlo & ~0xffff) | (val & 0xffff);
+ *loc = insnlo;
+ break;
+ }
+#endif
+