Saturday, June 2, 2012

Note on PowerPC relocations

It turns out that the #ha function, defined as #ha(x) = (((x >> 16) + ((x & 0x8000) ? 1 : 0)) & 0xFFFF) in the System V Application Binary Interface: PowerPC Processor Supplement, can also be implemented as #ha(x) = ((x + 0x8000) >> 16) & 0xFFFF, or simply #ha(x) = #hi(x + 0x8000):

Prelude Data.Bits Data.Int> let ha :: Int32 -> Int16; ha x = fromIntegral (x `shiftR` 16) + (if testBit x 15 then 1 else 0)
Prelude Data.Bits Data.Int> let hi :: Int32 -> Int16; hi x = fromIntegral (x `shiftR` 16)
Prelude Data.Bits Data.Int> all (\x -> ha x == hi (x + 0x8000)) [-0x20000..0x20000]

This could be useful in IDA, which does not have an offset type appropriate for R_PPC_ADDR16_HA relocations.