+-- Make code which causes a jump to the given address. This is the
+-- only arch-dependent bit of the itbl story. The returned list is
+-- itblCodeLength elements (bytes) long.
+
+-- For sparc_TARGET_ARCH, i386_TARGET_ARCH, etc.
+#include "nativeGen/NCG.h"
+
+itblCodeLength :: Int
+itblCodeLength = length (mkJumpToAddr undefined)
+
+mkJumpToAddr :: Ptr () -> [ItblCode]
+
+ptrToInt (Ptr a#) = I# (addr2Int# a#)
+
+#if sparc_TARGET_ARCH
+-- After some consideration, we'll try this, where
+-- 0x55555555 stands in for the address to jump to.
+-- According to ghc/includes/MachRegs.h, %g3 is very
+-- likely indeed to be baggable.
+--
+-- 0000 07155555 sethi %hi(0x55555555), %g3
+-- 0004 8610E155 or %g3, %lo(0x55555555), %g3
+-- 0008 81C0C000 jmp %g3
+-- 000c 01000000 nop
+
+type ItblCode = Word32
+mkJumpToAddr a
+ = let w32 = fromIntegral (ptrToInt a)
+
+ hi22, lo10 :: Word32 -> Word32
+ lo10 x = x .&. 0x3FF
+ hi22 x = (x `shiftR` 10) .&. 0x3FFFF
+
+ in [ 0x07000000 .|. (hi22 w32),
+ 0x8610E000 .|. (lo10 w32),
+ 0x81C0C000,
+ 0x01000000 ]
+
+#elif powerpc_TARGET_ARCH
+-- We'll use r12, for no particular reason.
+-- 0xDEADBEEF stands for the adress:
+-- 3D80DEAD lis r12,0xDEAD
+-- 618CBEEF ori r12,r12,0xBEEF
+-- 7D8903A6 mtctr r12
+-- 4E800420 bctr
+
+type ItblCode = Word32
+mkJumpToAddr a =
+ let w32 = fromIntegral (ptrToInt a)
+ hi16 x = (x `shiftR` 16) .&. 0xFFFF
+ lo16 x = x .&. 0xFFFF
+ in [
+ 0x3D800000 .|. hi16 w32,
+ 0x618C0000 .|. lo16 w32,
+ 0x7D8903A6, 0x4E800420
+ ]
+
+#elif i386_TARGET_ARCH
+-- Let the address to jump to be 0xWWXXYYZZ.
+-- Generate movl $0xWWXXYYZZ,%eax ; jmp *%eax
+-- which is
+-- B8 ZZ YY XX WW FF E0
+
+type ItblCode = Word8
+mkJumpToAddr a
+ = let w32 = fromIntegral (ptrToInt a)
+ insnBytes :: [Word8]
+ insnBytes
+ = [0xB8, byte 0 w32, byte 1 w32,
+ byte 2 w32, byte 3 w32,
+ 0xFF, 0xE0]
+ in
+ insnBytes
+
+#elif alpha_TARGET_ARCH
+type ItblCode = Word32
+mkJumpToAddr a
+ = [ 0xc3800000 -- br at, .+4
+ , 0xa79c000c -- ldq at, 12(at)
+ , 0x6bfc0000 -- jmp (at) # with zero hint -- oh well
+ , 0x47ff041f -- nop
+ , fromIntegral (w64 .&. 0x0000FFFF)
+ , fromIntegral ((w64 `shiftR` 32) .&. 0x0000FFFF) ]
+ where w64 = fromIntegral (ptrToInt a) :: Word64
+
+#else
+type ItblCode = Word32
+mkJumpToAddr a
+ = undefined
+#endif
+
+
+byte :: Int -> Word32 -> Word8
+byte 0 w = fromIntegral (w .&. 0xFF)
+byte 1 w = fromIntegral ((w `shiftR` 8) .&. 0xFF)
+byte 2 w = fromIntegral ((w `shiftR` 16) .&. 0xFF)
+byte 3 w = fromIntegral ((w `shiftR` 24) .&. 0xFF)