module GHC.CmmToAsm.X86.Regs (
virtualRegSqueeze,
realRegSqueeze,
Imm(..),
strImmLit,
litToImm,
AddrMode(..),
addrOffset,
spRel,
argRegs,
allArgRegs,
allIntArgRegs,
callClobberedRegs,
instrClobberedRegs,
allMachRegNos,
classOfRealReg,
showReg,
EABase(..), EAIndex(..), addrModeRegs,
eax, ebx, ecx, edx, esi, edi, ebp, esp,
rax, rbx, rcx, rdx, rsi, rdi, rbp, rsp,
r8, r9, r10, r11, r12, r13, r14, r15,
lastint,
xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7,
xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15,
xmm,
firstxmm, lastxmm,
ripRel,
allFPArgRegs,
allocatableRegs
)
where
#include "HsVersions.h"
import GHC.Prelude
import GHC.Platform.Regs
import GHC.Platform.Reg
import GHC.Platform.Reg.Class
import GHC.Cmm
import GHC.Cmm.CLabel ( CLabel )
import GHC.Utils.Outputable
import GHC.Utils.Panic
import GHC.Platform
import qualified Data.Array as A
virtualRegSqueeze :: RegClass -> VirtualReg -> Int
virtualRegSqueeze cls vr
= case cls of
RcInteger
-> case vr of
VirtualRegI{} -> 1
VirtualRegHi{} -> 1
_other -> 0
RcDouble
-> case vr of
VirtualRegD{} -> 1
VirtualRegF{} -> 0
_other -> 0
_other -> 0
realRegSqueeze :: RegClass -> RealReg -> Int
realRegSqueeze cls rr
= case cls of
RcInteger
-> case rr of
RealRegSingle regNo
| regNo < firstxmm -> 1
| otherwise -> 0
RealRegPair{} -> 0
RcDouble
-> case rr of
RealRegSingle regNo
| regNo >= firstxmm -> 1
| otherwise -> 0
RealRegPair{} -> 0
_other -> 0
data Imm
= ImmInt Int
| ImmInteger Integer
| ImmCLbl CLabel
| ImmLit SDoc
| ImmIndex CLabel Int
| ImmFloat Rational
| ImmDouble Rational
| ImmConstantSum Imm Imm
| ImmConstantDiff Imm Imm
strImmLit :: String -> Imm
strImmLit s = ImmLit (text s)
litToImm :: CmmLit -> Imm
litToImm (CmmInt i w) = ImmInteger (narrowS w i)
litToImm (CmmFloat f W32) = ImmFloat f
litToImm (CmmFloat f W64) = ImmDouble f
litToImm (CmmLabel l) = ImmCLbl l
litToImm (CmmLabelOff l off) = ImmIndex l off
litToImm (CmmLabelDiffOff l1 l2 off _)
= ImmConstantSum
(ImmConstantDiff (ImmCLbl l1) (ImmCLbl l2))
(ImmInt off)
litToImm _ = panic "X86.Regs.litToImm: no match"
data AddrMode
= AddrBaseIndex EABase EAIndex Displacement
| ImmAddr Imm Int
data EABase = EABaseNone | EABaseReg Reg | EABaseRip
data EAIndex = EAIndexNone | EAIndex Reg Int
type Displacement = Imm
addrOffset :: AddrMode -> Int -> Maybe AddrMode
addrOffset addr off
= case addr of
ImmAddr i off0 -> Just (ImmAddr i (off0 + off))
AddrBaseIndex r i (ImmInt n) -> Just (AddrBaseIndex r i (ImmInt (n + off)))
AddrBaseIndex r i (ImmInteger n)
-> Just (AddrBaseIndex r i (ImmInt (fromInteger (n + toInteger off))))
AddrBaseIndex r i (ImmCLbl lbl)
-> Just (AddrBaseIndex r i (ImmIndex lbl off))
AddrBaseIndex r i (ImmIndex lbl ix)
-> Just (AddrBaseIndex r i (ImmIndex lbl (ix+off)))
_ -> Nothing
addrModeRegs :: AddrMode -> [Reg]
addrModeRegs (AddrBaseIndex b i _) = b_regs ++ i_regs
where
b_regs = case b of { EABaseReg r -> [r]; _ -> [] }
i_regs = case i of { EAIndex r _ -> [r]; _ -> [] }
addrModeRegs _ = []
spRel :: Platform
-> Int
-> AddrMode
spRel platform n
| target32Bit platform
= AddrBaseIndex (EABaseReg esp) EAIndexNone (ImmInt n)
| otherwise
= AddrBaseIndex (EABaseReg rsp) EAIndexNone (ImmInt n)
firstxmm :: RegNo
firstxmm = 16
lastxmm :: Platform -> RegNo
lastxmm platform
| target32Bit platform = firstxmm + 7
| otherwise = firstxmm + 15
lastint :: Platform -> RegNo
lastint platform
| target32Bit platform = 7
| otherwise = 15
intregnos :: Platform -> [RegNo]
intregnos platform = [0 .. lastint platform]
xmmregnos :: Platform -> [RegNo]
xmmregnos platform = [firstxmm .. lastxmm platform]
floatregnos :: Platform -> [RegNo]
floatregnos platform = xmmregnos platform
argRegs :: RegNo -> [Reg]
argRegs _ = panic "MachRegs.argRegs(x86): should not be used!"
allMachRegNos :: Platform -> [RegNo]
allMachRegNos platform = intregnos platform ++ floatregnos platform
classOfRealReg :: Platform -> RealReg -> RegClass
classOfRealReg platform reg
= case reg of
RealRegSingle i
| i <= lastint platform -> RcInteger
| i <= lastxmm platform -> RcDouble
| otherwise -> panic "X86.Reg.classOfRealReg registerSingle too high"
_ -> panic "X86.Regs.classOfRealReg: RegPairs on this arch"
showReg :: Platform -> RegNo -> String
showReg platform n
| n >= firstxmm && n <= lastxmm platform = "%xmm" ++ show (nfirstxmm)
| n >= 8 && n < firstxmm = "%r" ++ show n
| otherwise = regNames platform A.! n
regNames :: Platform -> A.Array Int String
regNames platform
= if target32Bit platform
then A.listArray (0,8) ["%eax", "%ebx", "%ecx", "%edx", "%esi", "%edi", "%ebp", "%esp"]
else A.listArray (0,8) ["%rax", "%rbx", "%rcx", "%rdx", "%rsi", "%rdi", "%rbp", "%rsp"]
eax, ebx, ecx, edx, esp, ebp, esi, edi :: Reg
eax = regSingle 0
ebx = regSingle 1
ecx = regSingle 2
edx = regSingle 3
esi = regSingle 4
edi = regSingle 5
ebp = regSingle 6
esp = regSingle 7
rax, rbx, rcx, rdx, rsp, rbp, rsi, rdi,
r8, r9, r10, r11, r12, r13, r14, r15,
xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7,
xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15 :: Reg
rax = regSingle 0
rbx = regSingle 1
rcx = regSingle 2
rdx = regSingle 3
rsi = regSingle 4
rdi = regSingle 5
rbp = regSingle 6
rsp = regSingle 7
r8 = regSingle 8
r9 = regSingle 9
r10 = regSingle 10
r11 = regSingle 11
r12 = regSingle 12
r13 = regSingle 13
r14 = regSingle 14
r15 = regSingle 15
xmm0 = regSingle 16
xmm1 = regSingle 17
xmm2 = regSingle 18
xmm3 = regSingle 19
xmm4 = regSingle 20
xmm5 = regSingle 21
xmm6 = regSingle 22
xmm7 = regSingle 23
xmm8 = regSingle 24
xmm9 = regSingle 25
xmm10 = regSingle 26
xmm11 = regSingle 27
xmm12 = regSingle 28
xmm13 = regSingle 29
xmm14 = regSingle 30
xmm15 = regSingle 31
ripRel :: Displacement -> AddrMode
ripRel imm = AddrBaseIndex EABaseRip EAIndexNone imm
xmm :: RegNo -> Reg
xmm n = regSingle (firstxmm+n)
callClobberedRegs :: Platform -> [Reg]
callClobberedRegs platform
| target32Bit platform = [eax,ecx,edx] ++ map regSingle (floatregnos platform)
| platformOS platform == OSMinGW32
= [rax,rcx,rdx,r8,r9,r10,r11]
++ map xmm [0 .. 5]
| otherwise
= [rax,rcx,rdx,rsi,rdi,r8,r9,r10,r11]
++ map regSingle (floatregnos platform)
allArgRegs :: Platform -> [(Reg, Reg)]
allArgRegs platform
| platformOS platform == OSMinGW32 = zip [rcx,rdx,r8,r9]
(map regSingle [firstxmm ..])
| otherwise = panic "X86.Regs.allArgRegs: not defined for this arch"
allIntArgRegs :: Platform -> [Reg]
allIntArgRegs platform
| (platformOS platform == OSMinGW32) || target32Bit platform
= panic "X86.Regs.allIntArgRegs: not defined for this platform"
| otherwise = [rdi,rsi,rdx,rcx,r8,r9]
allFPArgRegs :: Platform -> [Reg]
allFPArgRegs platform
| platformOS platform == OSMinGW32
= panic "X86.Regs.allFPArgRegs: not defined for this platform"
| otherwise = map regSingle [firstxmm .. firstxmm + 7 ]
instrClobberedRegs :: Platform -> [Reg]
instrClobberedRegs platform
| target32Bit platform = [ eax, ecx, edx ]
| otherwise = [ rax, rcx, rdx ]
allocatableRegs :: Platform -> [RealReg]
allocatableRegs platform
= let isFree i = freeReg platform i
in map RealRegSingle $ filter isFree (allMachRegNos platform)