module SPARC.Regs (
        
        showReg,
        virtualRegSqueeze,
        realRegSqueeze,
        classOfRealReg,
        allRealRegs,
        
        gReg, iReg, lReg, oReg, fReg,
        fp, sp, g0, g1, g2, o0, o1, f0, f1, f6, f8, f22, f26, f27,
        
        allocatableRegs,
        
        argRegs,
        allArgRegs,
        callClobberedRegs,
        
        mkVirtualReg,
        regDotColor
)
where
import GhcPrelude
import CodeGen.Platform.SPARC
import Reg
import RegClass
import Format
import Unique
import Outputable
showReg :: RegNo -> String
showReg n
        | n >= 0  && n < 8   = "%g" ++ show n
        | n >= 8  && n < 16  = "%o" ++ show (n-8)
        | n >= 16 && n < 24  = "%l" ++ show (n-16)
        | n >= 24 && n < 32  = "%i" ++ show (n-24)
        | n >= 32 && n < 64  = "%f" ++ show (n-32)
        | otherwise          = panic "SPARC.Regs.showReg: unknown sparc register"
classOfRealReg :: RealReg -> RegClass
classOfRealReg reg
 = case reg of
        RealRegSingle i
                | i < 32        -> RcInteger
                | otherwise     -> RcFloat
        RealRegPair{}           -> RcDouble
{-# INLINE virtualRegSqueeze #-}
virtualRegSqueeze :: RegClass -> VirtualReg -> Int
virtualRegSqueeze cls vr
 = case cls of
        RcInteger
         -> case vr of
                VirtualRegI{}           -> 1
                VirtualRegHi{}          -> 1
                _other                  -> 0
        RcFloat
         -> case vr of
                VirtualRegF{}           -> 1
                VirtualRegD{}           -> 2
                _other                  -> 0
        RcDouble
         -> case vr of
                VirtualRegF{}           -> 1
                VirtualRegD{}           -> 1
                _other                  -> 0
{-# INLINE realRegSqueeze #-}
realRegSqueeze :: RegClass -> RealReg -> Int
realRegSqueeze cls rr
 = case cls of
        RcInteger
         -> case rr of
                RealRegSingle regNo
                        | regNo < 32    -> 1
                        | otherwise     -> 0
                RealRegPair{}           -> 0
        RcFloat
         -> case rr of
                RealRegSingle regNo
                        | regNo < 32    -> 0
                        | otherwise     -> 1
                RealRegPair{}           -> 2
        RcDouble
         -> case rr of
                RealRegSingle regNo
                        | regNo < 32    -> 0
                        | otherwise     -> 1
                RealRegPair{}           -> 1
allRealRegs :: [RealReg]
allRealRegs
        =  [ (RealRegSingle i)          | i <- [0..63] ]
        ++ [ (RealRegPair   i (i+1))    | i <- [32, 34 .. 62 ] ]
gReg, lReg, iReg, oReg, fReg :: Int -> RegNo
gReg x  = x             
oReg x  = (8 + x)       
lReg x  = (16 + x)      
iReg x  = (24 + x)      
fReg x  = (32 + x)      
g0, g1, g2, fp, sp, o0, o1, f0, f1, f6, f8, f22, f26, f27 :: Reg
f6  = RegReal (RealRegSingle (fReg 6))
f8  = RegReal (RealRegSingle (fReg 8))
f22 = RegReal (RealRegSingle (fReg 22))
f26 = RegReal (RealRegSingle (fReg 26))
f27 = RegReal (RealRegSingle (fReg 27))
g0  = RegReal (RealRegSingle (gReg 0))
g1  = RegReal (RealRegSingle (gReg 1))
g2  = RegReal (RealRegSingle (gReg 2))
fp  = RegReal (RealRegSingle (iReg 6))
sp  = RegReal (RealRegSingle (oReg 6))
o0  = RegReal (RealRegSingle (oReg 0))
o1  = RegReal (RealRegSingle (oReg 1))
f0  = RegReal (RealRegSingle (fReg 0))
f1  = RegReal (RealRegSingle (fReg 1))
allocatableRegs :: [RealReg]
allocatableRegs
   = let isFree rr
           = case rr of
                RealRegSingle r     -> freeReg r
                RealRegPair   r1 r2 -> freeReg r1 && freeReg r2
     in filter isFree allRealRegs
argRegs :: RegNo -> [Reg]
argRegs r
 = case r of
        0       -> []
        1       -> map (RegReal . RealRegSingle . oReg) [0]
        2       -> map (RegReal . RealRegSingle . oReg) [0,1]
        3       -> map (RegReal . RealRegSingle . oReg) [0,1,2]
        4       -> map (RegReal . RealRegSingle . oReg) [0,1,2,3]
        5       -> map (RegReal . RealRegSingle . oReg) [0,1,2,3,4]
        6       -> map (RegReal . RealRegSingle . oReg) [0,1,2,3,4,5]
        _       -> panic "MachRegs.argRegs(sparc): don't know about >6 arguments!"
allArgRegs :: [Reg]
allArgRegs
        = map (RegReal . RealRegSingle) [oReg i | i <- [0..5]]
callClobberedRegs :: [Reg]
callClobberedRegs
        = map (RegReal . RealRegSingle)
                (  oReg 7 :
                  [oReg i | i <- [0..5]] ++
                  [gReg i | i <- [1..7]] ++
                  [fReg i | i <- [0..31]] )
mkVirtualReg :: Unique -> Format -> VirtualReg
mkVirtualReg u format
        | not (isFloatFormat format)
        = VirtualRegI u
        | otherwise
        = case format of
                FF32    -> VirtualRegF u
                FF64    -> VirtualRegD u
                _       -> panic "mkVReg"
regDotColor :: RealReg -> SDoc
regDotColor reg
 = case classOfRealReg reg of
        RcInteger       -> text "blue"
        RcFloat         -> text "red"
        _other          -> text "green"