module X86.Regs (
virtualRegSqueeze,
realRegSqueeze,
Imm(..),
strImmLit,
litToImm,
AddrMode(..),
addrOffset,
spRel,
argRegs,
allArgRegs,
allIntArgRegs,
allHaskellArgRegs,
callClobberedRegs,
instrClobberedRegs,
allMachRegNos,
classOfRealReg,
showReg,
EABase(..), EAIndex(..), addrModeRegs,
eax, ebx, ecx, edx, esi, edi, ebp, esp,
fake0, fake1, fake2, fake3, fake4, fake5, firstfake,
rax, rbx, rcx, rdx, rsi, rdi, rbp, rsp,
r8, r9, r10, r11, r12, r13, r14, r15,
xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7,
xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15,
xmm,
ripRel,
allFPArgRegs,
freeReg,
globalRegMaybe,
allocatableRegs
)
where
#include "nativeGen/NCG.h"
#include "HsVersions.h"
#include "../includes/stg/MachRegs.h"
import Reg
import RegClass
import BlockId
import OldCmm
import CmmCallConv
import CLabel ( CLabel )
import Outputable
import Platform
import FastTypes
import FastBool
import Constants
virtualRegSqueeze :: RegClass -> VirtualReg -> FastInt
virtualRegSqueeze cls vr
= case cls of
RcInteger
-> case vr of
VirtualRegI{} -> _ILIT(1)
VirtualRegHi{} -> _ILIT(1)
_other -> _ILIT(0)
RcDouble
-> case vr of
VirtualRegD{} -> _ILIT(1)
VirtualRegF{} -> _ILIT(0)
_other -> _ILIT(0)
RcDoubleSSE
-> case vr of
VirtualRegSSE{} -> _ILIT(1)
_other -> _ILIT(0)
_other -> _ILIT(0)
realRegSqueeze :: RegClass -> RealReg -> FastInt
realRegSqueeze cls rr
= case cls of
RcInteger
-> case rr of
RealRegSingle regNo
| regNo < firstfake -> _ILIT(1)
| otherwise -> _ILIT(0)
RealRegPair{} -> _ILIT(0)
RcDouble
-> case rr of
RealRegSingle regNo
| regNo >= firstfake && regNo <= lastfake -> _ILIT(1)
| otherwise -> _ILIT(0)
RealRegPair{} -> _ILIT(0)
RcDoubleSSE
-> case rr of
RealRegSingle regNo | regNo >= firstxmm -> _ILIT(1)
_otherwise -> _ILIT(0)
_other -> _ILIT(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 (CmmBlock id) = ImmCLbl (infoTblLbl id)
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 * wORD_SIZE))
| otherwise
= AddrBaseIndex (EABaseReg rsp) EAIndexNone (ImmInt (n * wORD_SIZE))
firstfake, lastfake :: RegNo
firstfake = 16
lastfake = 21
firstxmm, lastxmm :: RegNo
firstxmm = 24
#if i386_TARGET_ARCH
lastxmm = 31
#else
lastxmm = 39
#endif
lastint :: RegNo
#if i386_TARGET_ARCH
lastint = 7
#else
lastint = 15
#endif
intregnos, fakeregnos, xmmregnos, floatregnos :: [RegNo]
intregnos = [0..lastint]
fakeregnos = [firstfake .. lastfake]
xmmregnos = [firstxmm .. lastxmm]
floatregnos = fakeregnos ++ xmmregnos;
argRegs :: RegNo -> [Reg]
argRegs _ = panic "MachRegs.argRegs(x86): should not be used!"
allMachRegNos :: [RegNo]
allMachRegNos = intregnos ++ floatregnos
classOfRealReg :: RealReg -> RegClass
classOfRealReg reg
= case reg of
RealRegSingle i
| i <= lastint -> RcInteger
| i <= lastfake -> RcDouble
| otherwise -> RcDoubleSSE
RealRegPair{} -> panic "X86.Regs.classOfRealReg: RegPairs on this arch"
showReg :: Platform -> RegNo -> String
showReg platform n
| n >= firstxmm = "%xmm" ++ show (nfirstxmm)
| n >= firstfake = "%fake" ++ show (nfirstfake)
| n >= 8 = "%r" ++ show n
| otherwise = regNames platform !! n
regNames :: Platform -> [String]
regNames platform
= if target32Bit platform
then ["%eax", "%ebx", "%ecx", "%edx", "%esi", "%edi", "%ebp", "%esp"]
else ["%rax", "%rbx", "%rcx", "%rdx", "%rsi", "%rdi", "%rbp", "%rsp"]
fake0, fake1, fake2, fake3, fake4, fake5,
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
fake0 = regSingle 16
fake1 = regSingle 17
fake2 = regSingle 18
fake3 = regSingle 19
fake4 = regSingle 20
fake5 = regSingle 21
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 24
xmm1 = regSingle 25
xmm2 = regSingle 26
xmm3 = regSingle 27
xmm4 = regSingle 28
xmm5 = regSingle 29
xmm6 = regSingle 30
xmm7 = regSingle 31
xmm8 = regSingle 32
xmm9 = regSingle 33
xmm10 = regSingle 34
xmm11 = regSingle 35
xmm12 = regSingle 36
xmm13 = regSingle 37
xmm14 = regSingle 38
xmm15 = regSingle 39
ripRel :: Displacement -> AddrMode
ripRel imm = AddrBaseIndex EABaseRip EAIndexNone imm
xmm :: RegNo -> Reg
xmm n = regSingle (firstxmm+n)
freeReg :: RegNo -> FastBool
globalRegMaybe :: GlobalReg -> Maybe RealReg
allArgRegs :: [(Reg, Reg)]
allIntArgRegs :: [Reg]
allFPArgRegs :: [Reg]
callClobberedRegs :: [Reg]
#if defined(i386_TARGET_ARCH) || defined(x86_64_TARGET_ARCH)
#if i386_TARGET_ARCH
#define eax 0
#define ebx 1
#define ecx 2
#define edx 3
#define esi 4
#define edi 5
#define ebp 6
#define esp 7
#endif
#if x86_64_TARGET_ARCH
#define rax 0
#define rbx 1
#define rcx 2
#define rdx 3
#define rsi 4
#define rdi 5
#define rbp 6
#define rsp 7
#define r8 8
#define r9 9
#define r10 10
#define r11 11
#define r12 12
#define r13 13
#define r14 14
#define r15 15
#endif
#define fake0 16
#define fake1 17
#define fake2 18
#define fake3 19
#define fake4 20
#define fake5 21
#define xmm0 24
#define xmm1 25
#define xmm2 26
#define xmm3 27
#define xmm4 28
#define xmm5 29
#define xmm6 30
#define xmm7 31
#define xmm8 32
#define xmm9 33
#define xmm10 34
#define xmm11 35
#define xmm12 36
#define xmm13 37
#define xmm14 38
#define xmm15 39
#if i386_TARGET_ARCH
freeReg esp = fastBool False
#endif
#if i386_TARGET_ARCH
freeReg esi = fastBool False
freeReg edi = fastBool False
#endif
#if x86_64_TARGET_ARCH
freeReg rsp = fastBool False
#endif
freeReg r = freeRegBase r
freeRegBase :: RegNo -> FastBool
#ifdef REG_Base
freeRegBase REG_Base = fastBool False
#endif
#ifdef REG_Sp
freeRegBase REG_Sp = fastBool False
#endif
#ifdef REG_SpLim
freeRegBase REG_SpLim = fastBool False
#endif
#ifdef REG_Hp
freeRegBase REG_Hp = fastBool False
#endif
#ifdef REG_HpLim
freeRegBase REG_HpLim = fastBool False
#endif
freeRegBase _ = fastBool True
#ifdef REG_Base
globalRegMaybe BaseReg = Just (RealRegSingle REG_Base)
#endif
#ifdef REG_R1
globalRegMaybe (VanillaReg 1 _) = Just (RealRegSingle REG_R1)
#endif
#ifdef REG_R2
globalRegMaybe (VanillaReg 2 _) = Just (RealRegSingle REG_R2)
#endif
#ifdef REG_R3
globalRegMaybe (VanillaReg 3 _) = Just (RealRegSingle REG_R3)
#endif
#ifdef REG_R4
globalRegMaybe (VanillaReg 4 _) = Just (RealRegSingle REG_R4)
#endif
#ifdef REG_R5
globalRegMaybe (VanillaReg 5 _) = Just (RealRegSingle REG_R5)
#endif
#ifdef REG_R6
globalRegMaybe (VanillaReg 6 _) = Just (RealRegSingle REG_R6)
#endif
#ifdef REG_R7
globalRegMaybe (VanillaReg 7 _) = Just (RealRegSingle REG_R7)
#endif
#ifdef REG_R8
globalRegMaybe (VanillaReg 8 _) = Just (RealRegSingle REG_R8)
#endif
#ifdef REG_R9
globalRegMaybe (VanillaReg 9 _) = Just (RealRegSingle REG_R9)
#endif
#ifdef REG_R10
globalRegMaybe (VanillaReg 10 _) = Just (RealRegSingle REG_R10)
#endif
#ifdef REG_F1
globalRegMaybe (FloatReg 1) = Just (RealRegSingle REG_F1)
#endif
#ifdef REG_F2
globalRegMaybe (FloatReg 2) = Just (RealRegSingle REG_F2)
#endif
#ifdef REG_F3
globalRegMaybe (FloatReg 3) = Just (RealRegSingle REG_F3)
#endif
#ifdef REG_F4
globalRegMaybe (FloatReg 4) = Just (RealRegSingle REG_F4)
#endif
#ifdef REG_D1
globalRegMaybe (DoubleReg 1) = Just (RealRegSingle REG_D1)
#endif
#ifdef REG_D2
globalRegMaybe (DoubleReg 2) = Just (RealRegSingle REG_D2)
#endif
#ifdef REG_Sp
globalRegMaybe Sp = Just (RealRegSingle REG_Sp)
#endif
#ifdef REG_Lng1
globalRegMaybe (LongReg 1) = Just (RealRegSingle REG_Lng1)
#endif
#ifdef REG_Lng2
globalRegMaybe (LongReg 2) = Just (RealRegSingle REG_Lng2)
#endif
#ifdef REG_SpLim
globalRegMaybe SpLim = Just (RealRegSingle REG_SpLim)
#endif
#ifdef REG_Hp
globalRegMaybe Hp = Just (RealRegSingle REG_Hp)
#endif
#ifdef REG_HpLim
globalRegMaybe HpLim = Just (RealRegSingle REG_HpLim)
#endif
#ifdef REG_CurrentTSO
globalRegMaybe CurrentTSO = Just (RealRegSingle REG_CurrentTSO)
#endif
#ifdef REG_CurrentNursery
globalRegMaybe CurrentNursery = Just (RealRegSingle REG_CurrentNursery)
#endif
globalRegMaybe _ = Nothing
#if defined(mingw32_HOST_OS) && x86_64_TARGET_ARCH
allArgRegs = zip (map regSingle [rcx,rdx,r8,r9])
(map regSingle [firstxmm ..])
allIntArgRegs = panic "X86.Regs.allIntArgRegs: not defined for this platform"
allFPArgRegs = panic "X86.Regs.allFPArgRegs: not defined for this platform"
#else
allArgRegs = panic "X86.Regs.allArgRegs: not defined for this arch"
# if i386_TARGET_ARCH
allIntArgRegs = panic "X86.Regs.allIntArgRegs: should not be used!"
# elif x86_64_TARGET_ARCH
allIntArgRegs = map regSingle [rdi,rsi,rdx,rcx,r8,r9]
# else
allIntArgRegs = panic "X86.Regs.allIntArgRegs: not defined for this arch"
# endif
allFPArgRegs = map regSingle [firstxmm .. firstxmm+7]
#endif
allHaskellArgRegs :: [Reg]
allHaskellArgRegs = [ RegReal r | Just r <- map globalRegMaybe globalArgRegs ]
instrClobberedRegs :: [RealReg]
#if i386_TARGET_ARCH
instrClobberedRegs = map RealRegSingle [ eax, ecx, edx ]
#elif x86_64_TARGET_ARCH
instrClobberedRegs = map RealRegSingle [ rax, rcx, rdx ]
#endif
#if i386_TARGET_ARCH
callClobberedRegs
= map regSingle ([eax,ecx,edx] ++ floatregnos)
#elif x86_64_TARGET_ARCH
callClobberedRegs
= map regSingle ([rax,rcx,rdx,rsi,rdi,r8,r9,r10,r11] ++ floatregnos)
#else
callClobberedRegs
= panic "X86.Regs.callClobberedRegs: not defined for this architecture"
#endif
#else /* i386_TARGET_ARCH || x86_64_TARGET_ARCH */
freeReg _ = 0#
globalRegMaybe _ = panic "X86.Regs.globalRegMaybe: not defined"
allArgRegs = panic "X86.Regs.allArgRegs: not defined"
allIntArgRegs = panic "X86.Regs.allIntArgRegs: not defined"
allFPArgRegs = panic "X86.Regs.allFPArgRegs: not defined"
callClobberedRegs = panic "X86.Regs.callClobberedRegs: not defined"
instrClobberedRegs :: [RealReg]
instrClobberedRegs = panic "X86.Regs.instrClobberedRegs: not defined for this arch"
allHaskellArgRegs :: [Reg]
allHaskellArgRegs = panic "X86.Regs.allHaskellArgRegs: not defined for this arch"
#endif
allocatableRegs :: [RealReg]
allocatableRegs
= let isFree i = isFastTrue (freeReg i)
in map RealRegSingle $ filter isFree allMachRegNos