content: 
  -- | A description of the register set of the X86.
  --
  --   This isn't used directly in GHC proper.
  --
  --   See RegArchBase.hs for the reference.
  --   See MachRegs.hs for the actual trivColorable function used in GHC.
  --
  module GHC.CmmToAsm.Reg.Graph.X86 (
          classOfReg,
          regsOfClass,
          regName,
          regAlias,
          worst,
          squeese,
  ) where
  
  import GHC.Prelude
  
  import GHC.CmmToAsm.Reg.Graph.Base  (Reg(..), RegSub(..), RegClass(..))
  import GHC.Types.Unique.Set
  
  import qualified Data.Array as A
  
  
  -- | Determine the class of a register
  classOfReg :: Reg -> RegClass
  classOfReg reg
   = case reg of
          Reg c _         -> c
  
          RegSub SubL16 _ -> ClassG16
          RegSub SubL8  _ -> ClassG8
          RegSub SubL8H _ -> ClassG8
  
  
  -- | Determine all the regs that make up a certain class.
  regsOfClass :: RegClass -> UniqSet Reg
  regsOfClass c
   = case c of
          ClassG32
           -> mkUniqSet   [ Reg ClassG32  i
                          | i <- [0..7] ]
  
          ClassG16
           -> mkUniqSet   [ RegSub SubL16 (Reg ClassG32 i)
                          | i <- [0..7] ]
  
          ClassG8
           -> unionUniqSets
                  (mkUniqSet [ RegSub SubL8  (Reg ClassG32 i) | i <- [0..3] ])
                  (mkUniqSet [ RegSub SubL8H (Reg ClassG32 i) | i <- [0..3] ])
  
          ClassF64
           -> mkUniqSet   [ Reg ClassF64  i
                          | i <- [0..5] ]
  
  
  -- | Determine the common name of a reg
  --      returns Nothing if this reg is not part of the machine.
  regName :: Reg -> Maybe String
  regName reg
   = case reg of
          Reg ClassG32 i
           | i <= 7 ->
             let names = A.listArray (0,8)
                         [ "eax", "ebx", "ecx", "edx"
                         , "ebp", "esi", "edi", "esp" ]
             in Just $ names A.! i
  
          RegSub SubL16 (Reg ClassG32 i)
           | i <= 7 ->
             let names = A.listArray (0,8)
                         [ "ax", "bx", "cx", "dx"
                         , "bp", "si", "di", "sp"]
             in Just $ names A.! i
  
          RegSub SubL8  (Reg ClassG32 i)
           | i <= 3 ->
             let names = A.listArray (0,4) [ "al", "bl", "cl", "dl"]
             in Just $ names A.! i
  
          RegSub SubL8H (Reg ClassG32 i)
           | i <= 3 ->
             let names = A.listArray (0,4) [ "ah", "bh", "ch", "dh"]
             in Just $ names A.! i
  
          _         -> Nothing
  
  
  -- | Which regs alias what other regs.
  regAlias :: Reg -> UniqSet Reg
  regAlias reg
   = case reg of
  
          -- 32 bit regs alias all of the subregs
          Reg ClassG32 i
  
           -- for eax, ebx, ecx, eds
           |  i <= 3
           -> mkUniqSet
           $ [ Reg ClassG32 i,   RegSub SubL16 reg
             , RegSub SubL8 reg, RegSub SubL8H reg ]
  
           -- for esi, edi, esp, ebp
           | 4 <= i && i <= 7
           -> mkUniqSet
           $ [ Reg ClassG32 i,   RegSub SubL16 reg ]
  
          -- 16 bit subregs alias the whole reg
          RegSub SubL16 r@(Reg ClassG32 _)
           ->     regAlias r
  
          -- 8 bit subregs alias the 32 and 16, but not the other 8 bit subreg
          RegSub SubL8  r@(Reg ClassG32 _)
           -> mkUniqSet $ [ r, RegSub SubL16 r, RegSub SubL8 r ]
  
          RegSub SubL8H r@(Reg ClassG32 _)
           -> mkUniqSet $ [ r, RegSub SubL16 r, RegSub SubL8H r ]
  
          -- fp
          Reg ClassF64 _
           -> unitUniqSet reg
  
          _ -> error "regAlias: invalid register"
  
  
  -- | Optimised versions of RegColorBase.{worst, squeese} specific to x86
  worst :: Int -> RegClass -> RegClass -> Int
  worst n classN classC
   = case classN of
          ClassG32
           -> case classC of
                  ClassG32        -> min n 8
                  ClassG16        -> min n 8
                  ClassG8         -> min n 4
                  ClassF64        -> 0
  
          ClassG16
           -> case classC of
                  ClassG32        -> min n 8
                  ClassG16        -> min n 8
                  ClassG8         -> min n 4
                  ClassF64        -> 0
  
          ClassG8
           -> case classC of
                  ClassG32        -> min (n*2) 8
                  ClassG16        -> min (n*2) 8
                  ClassG8         -> min n 8
                  ClassF64        -> 0
  
          ClassF64
           -> case classC of
                  ClassF64        -> min n 6
                  _               -> 0
  
  squeese :: RegClass -> [(Int, RegClass)] -> Int
  squeese classN countCs
          = sum (map (\(i, classC) -> worst i classN classC) countCs)
  
  