module X86.Regs (
-
- -- sizes
- Size(..),
- intSize,
- floatSize,
- isFloatSize,
- wordSize,
- cmmTypeSize,
- sizeToWidth,
- mkVReg,
+ -- squeese functions for the graph allocator
+ virtualRegSqueeze,
+ realRegSqueeze,
-- immediates
Imm(..),
allArgRegs,
callClobberedRegs,
allMachRegNos,
- regClass,
+ classOfRealReg,
showReg,
-- machine specific
EABase(..), EAIndex(..), addrModeRegs,
eax, ebx, ecx, edx, esi, edi, ebp, esp,
- fake0, fake1, fake2, fake3, fake4, fake5,
+ fake0, fake1, fake2, fake3, fake4, fake5, firstfake,
rax, rbx, rcx, rdx, rsi, rdi, rbp, rsp,
r8, r9, r10, r11, r12, r13, r14, r15,
-- horror show
freeReg,
- globalRegMaybe
+ globalRegMaybe,
+
+ allocatableRegs
)
where
#include "nativeGen/NCG.h"
#include "HsVersions.h"
-#if i386_TARGET_ARCH
-# define STOLEN_X86_REGS 4
--- HACK: go for the max
-#endif
+#include "../includes/stg/MachRegs.h"
-#include "../includes/MachRegs.h"
-
-import RegsBase
+import Reg
+import RegClass
import BlockId
-import Cmm
+import OldCmm
import CLabel ( CLabel )
import Pretty
-import Outputable ( Outputable(..), pprPanic, panic )
-import qualified Outputable
-import Unique
+import Outputable ( panic )
+import FastTypes
import FastBool
+
#if defined(i386_TARGET_ARCH) || defined(x86_64_TARGET_ARCH)
import Constants
#endif
--- -----------------------------------------------------------------------------
--- Sizes on this architecture
---
--- A Size is usually a combination of width and class
--- It looks very like the old MachRep, but it's now of purely local
--- significance, here in the native code generator. You can change it
--- without global consequences.
+-- | regSqueeze_class reg
+-- Calculuate the maximum number of register colors that could be
+-- denied to a node of this class due to having this reg
+-- as a neighbour.
--
--- A major use is as an opcode qualifier; thus the opcode
--- mov.l a b
--- might be encoded
--- MOV II32 a b
--- where the Size field encodes the ".l" part.
-
--- ToDo: it's not clear to me that we need separate signed-vs-unsigned sizes
--- here. I've removed them from the x86 version, we'll see what happens --SDM
-
--- ToDo: quite a few occurrences of Size could usefully be replaced by Width
-
-data Size
- = II8 | II16 | II32 | II64 | FF32 | FF64 | FF80
- deriving Eq
-
-intSize, floatSize :: Width -> Size
-intSize W8 = II8
-intSize W16 = II16
-intSize W32 = II32
-intSize W64 = II64
-intSize other = pprPanic "MachInstrs.intSize" (ppr other)
-
-
-floatSize W32 = FF32
-floatSize W64 = FF64
-floatSize other = pprPanic "MachInstrs.intSize" (ppr other)
-
-
-isFloatSize :: Size -> Bool
-isFloatSize FF32 = True
-isFloatSize FF64 = True
-isFloatSize FF80 = True
-isFloatSize _ = False
-
-
-wordSize :: Size
-wordSize = intSize wordWidth
-
-
-cmmTypeSize :: CmmType -> Size
-cmmTypeSize ty | isFloatType ty = floatSize (typeWidth ty)
- | otherwise = intSize (typeWidth ty)
-
-
-sizeToWidth :: Size -> Width
-sizeToWidth II8 = W8
-sizeToWidth II16 = W16
-sizeToWidth II32 = W32
-sizeToWidth II64 = W64
-sizeToWidth FF32 = W32
-sizeToWidth FF64 = W64
-sizeToWidth _ = panic "MachInstrs.sizeToWidth"
-
-
-mkVReg :: Unique -> Size -> Reg
-mkVReg u size
- | not (isFloatSize size) = VirtualRegI u
- | otherwise
- = case size of
- FF32 -> VirtualRegD u
- FF64 -> VirtualRegD u
- _ -> panic "mkVReg"
-
+{-# INLINE virtualRegSqueeze #-}
+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)
+
+{-# INLINE realRegSqueeze #-}
+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)
-- -----------------------------------------------------------------------------
-- Immediates
#endif
+-- The register numbers must fit into 32 bits on x86, so that we can
+-- use a Word32 to represent the set of free registers in the register
+-- allocator.
+
+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 -- not %r8..%r15
+#else
+lastint = 15
+#endif
+
+intregnos, fakeregnos, xmmregnos, floatregnos :: [RegNo]
+intregnos = [0..lastint]
+fakeregnos = [firstfake .. lastfake]
+xmmregnos = [firstxmm .. lastxmm]
+floatregnos = fakeregnos ++ xmmregnos;
+
-- argRegs is the set of regs which are read for an n-argument call to C.
-- For archs which pass all args on the stack (x86), is empty.
argRegs :: RegNo -> [Reg]
argRegs _ = panic "MachRegs.argRegs(x86): should not be used!"
-
-
-
-
-- | The complete set of machine registers.
allMachRegNos :: [RegNo]
-
-#if i386_TARGET_ARCH
-allMachRegNos = [0..13]
-
-#elif x86_64_TARGET_ARCH
-allMachRegNos = [0..31]
-
-#else
-allMachRegNos = panic "X86.Regs.callClobberedRegs: not defined for this architecture"
-
-#endif
-
+allMachRegNos = intregnos ++ floatregnos
-- | Take the class of a register.
-{-# INLINE regClass #-}
-regClass :: Reg -> RegClass
-
-#if i386_TARGET_ARCH
--- On x86, we might want to have an 8-bit RegClass, which would
--- contain just regs 1-4 (the others don't have 8-bit versions).
--- However, we can get away without this at the moment because the
--- only allocatable integer regs are also 8-bit compatible (1, 3, 4).
-regClass (RealReg i) = if i < 8 then RcInteger else RcDouble
-regClass (VirtualRegI _) = RcInteger
-regClass (VirtualRegHi _) = RcInteger
-regClass (VirtualRegD _) = RcDouble
-regClass (VirtualRegF u) = pprPanic ("regClass(x86):VirtualRegF") (ppr u)
-
-#elif x86_64_TARGET_ARCH
+{-# INLINE classOfRealReg #-}
+classOfRealReg :: RealReg -> RegClass
-- On x86, we might want to have an 8-bit RegClass, which would
-- contain just regs 1-4 (the others don't have 8-bit versions).
-- However, we can get away without this at the moment because the
-- only allocatable integer regs are also 8-bit compatible (1, 3, 4).
-regClass (RealReg i) = if i < 16 then RcInteger else RcDouble
-regClass (VirtualRegI _) = RcInteger
-regClass (VirtualRegHi _) = RcInteger
-regClass (VirtualRegD _) = RcDouble
-regClass (VirtualRegF u) = pprPanic "regClass(x86_64):VirtualRegF" (ppr u)
-
-#else
-regClass _ = panic "X86.Regs.regClass: not defined for this architecture"
-
-#endif
+classOfRealReg reg
+ = case reg of
+ RealRegSingle i
+ | i <= lastint -> RcInteger
+ | i <= lastfake -> RcDouble
+ | otherwise -> RcDoubleSSE
+ RealRegPair{} -> panic "X86.Regs.classOfRealReg: RegPairs on this arch"
-- | Get the name of the register with this number.
showReg :: RegNo -> String
-
-#if i386_TARGET_ARCH
showReg n
- = if n >= 0 && n < 14
- then regNames !! n
- else "%unknown_x86_real_reg_" ++ show n
+ | n >= firstxmm = "%xmm" ++ show (n-firstxmm)
+ | n >= firstfake = "%fake" ++ show (n-firstfake)
+ | n >= 8 = "%r" ++ show n
+ | otherwise = regNames !! n
regNames :: [String]
regNames
- = ["%eax", "%ebx", "%ecx", "%edx", "%esi", "%edi", "%ebp", "%esp",
- "%fake0", "%fake1", "%fake2", "%fake3", "%fake4", "%fake5", "%fake6"]
-
+#if i386_TARGET_ARCH
+ = ["%eax", "%ebx", "%ecx", "%edx", "%esi", "%edi", "%ebp", "%esp"]
#elif x86_64_TARGET_ARCH
-showReg n
- | n >= 16 = "%xmm" ++ show (n-16)
- | n >= 8 = "%r" ++ show n
- | otherwise = regNames !! n
-
-regNames :: [String]
-regNames
- = ["%rax", "%rbx", "%rcx", "%rdx", "%rsi", "%rdi", "%rbp", "%rsp" ]
-
+ = ["%rax", "%rbx", "%rcx", "%rdx", "%rsi", "%rdi", "%rbp", "%rsp" ]
#else
-showReg _ = panic "X86.Regs.showReg: not defined for this architecture"
-
+ = []
#endif
-
-- machine specific ------------------------------------------------------------
- Only ebx, esi, edi and esp are available across a C call (they are callee-saves).
- Registers 0-7 have 16-bit counterparts (ax, bx etc.)
- Registers 0-3 have 8 bit counterparts (ah, bh etc.)
-- Registers 8-13 are fakes; we pretend x86 has 6 conventionally-addressable
+- Registers fake0..fake5 are fakes; we pretend x86 has 6 conventionally-addressable
fp registers, and 3-operand insns for them, and we translate this into
real stack-based x86 fp code after register allocation.
fake0, fake1, fake2, fake3, fake4, fake5,
eax, ebx, ecx, edx, esp, ebp, esi, edi :: Reg
-eax = RealReg 0
-ebx = RealReg 1
-ecx = RealReg 2
-edx = RealReg 3
-esi = RealReg 4
-edi = RealReg 5
-ebp = RealReg 6
-esp = RealReg 7
-fake0 = RealReg 8
-fake1 = RealReg 9
-fake2 = RealReg 10
-fake3 = RealReg 11
-fake4 = RealReg 12
-fake5 = RealReg 13
+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
xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7,
xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15 :: Reg
-rax = RealReg 0
-rbx = RealReg 1
-rcx = RealReg 2
-rdx = RealReg 3
-rsi = RealReg 4
-rdi = RealReg 5
-rbp = RealReg 6
-rsp = RealReg 7
-r8 = RealReg 8
-r9 = RealReg 9
-r10 = RealReg 10
-r11 = RealReg 11
-r12 = RealReg 12
-r13 = RealReg 13
-r14 = RealReg 14
-r15 = RealReg 15
-xmm0 = RealReg 16
-xmm1 = RealReg 17
-xmm2 = RealReg 18
-xmm3 = RealReg 19
-xmm4 = RealReg 20
-xmm5 = RealReg 21
-xmm6 = RealReg 22
-xmm7 = RealReg 23
-xmm8 = RealReg 24
-xmm9 = RealReg 25
-xmm10 = RealReg 26
-xmm11 = RealReg 27
-xmm12 = RealReg 28
-xmm13 = RealReg 29
-xmm14 = RealReg 30
-xmm15 = RealReg 31
+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
allFPArgRegs :: [Reg]
-allFPArgRegs = map RealReg [16 .. 23]
+allFPArgRegs = map regSingle [firstxmm .. firstxmm+7]
ripRel :: Displacement -> AddrMode
ripRel imm = AddrBaseIndex EABaseRip EAIndexNone imm
-}
xmm :: RegNo -> Reg
-xmm n = RealReg (16+n)
+xmm n = regSingle (firstxmm+n)
-- horror show -----------------------------------------------------------------
freeReg :: RegNo -> FastBool
-globalRegMaybe :: GlobalReg -> Maybe Reg
+globalRegMaybe :: GlobalReg -> Maybe RealReg
allArgRegs :: [Reg]
callClobberedRegs :: [Reg]
#define edi 5
#define ebp 6
#define esp 7
-#define fake0 8
-#define fake1 9
-#define fake2 10
-#define fake3 11
-#define fake4 12
-#define fake5 13
#endif
#if x86_64_TARGET_ARCH
#define r13 13
#define r14 14
#define r15 15
-#define xmm0 16
-#define xmm1 17
-#define xmm2 18
-#define xmm3 19
-#define xmm4 20
-#define xmm5 21
-#define xmm6 22
-#define xmm7 23
-#define xmm8 24
-#define xmm9 25
-#define xmm10 26
-#define xmm11 27
-#define xmm12 28
-#define xmm13 29
-#define xmm14 30
-#define xmm15 31
#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 -- %esp is the C stack pointer
-- reg is the machine register it is stored in.
#ifdef REG_Base
-globalRegMaybe BaseReg = Just (RealReg REG_Base)
+globalRegMaybe BaseReg = Just (RealRegSingle REG_Base)
#endif
#ifdef REG_R1
-globalRegMaybe (VanillaReg 1 _) = Just (RealReg REG_R1)
+globalRegMaybe (VanillaReg 1 _) = Just (RealRegSingle REG_R1)
#endif
#ifdef REG_R2
-globalRegMaybe (VanillaReg 2 _) = Just (RealReg REG_R2)
+globalRegMaybe (VanillaReg 2 _) = Just (RealRegSingle REG_R2)
#endif
#ifdef REG_R3
-globalRegMaybe (VanillaReg 3 _) = Just (RealReg REG_R3)
+globalRegMaybe (VanillaReg 3 _) = Just (RealRegSingle REG_R3)
#endif
#ifdef REG_R4
-globalRegMaybe (VanillaReg 4 _) = Just (RealReg REG_R4)
+globalRegMaybe (VanillaReg 4 _) = Just (RealRegSingle REG_R4)
#endif
#ifdef REG_R5
-globalRegMaybe (VanillaReg 5 _) = Just (RealReg REG_R5)
+globalRegMaybe (VanillaReg 5 _) = Just (RealRegSingle REG_R5)
#endif
#ifdef REG_R6
-globalRegMaybe (VanillaReg 6 _) = Just (RealReg REG_R6)
+globalRegMaybe (VanillaReg 6 _) = Just (RealRegSingle REG_R6)
#endif
#ifdef REG_R7
-globalRegMaybe (VanillaReg 7 _) = Just (RealReg REG_R7)
+globalRegMaybe (VanillaReg 7 _) = Just (RealRegSingle REG_R7)
#endif
#ifdef REG_R8
-globalRegMaybe (VanillaReg 8 _) = Just (RealReg REG_R8)
+globalRegMaybe (VanillaReg 8 _) = Just (RealRegSingle REG_R8)
#endif
#ifdef REG_R9
-globalRegMaybe (VanillaReg 9 _) = Just (RealReg REG_R9)
+globalRegMaybe (VanillaReg 9 _) = Just (RealRegSingle REG_R9)
#endif
#ifdef REG_R10
-globalRegMaybe (VanillaReg 10 _) = Just (RealReg REG_R10)
+globalRegMaybe (VanillaReg 10 _) = Just (RealRegSingle REG_R10)
#endif
#ifdef REG_F1
-globalRegMaybe (FloatReg 1) = Just (RealReg REG_F1)
+globalRegMaybe (FloatReg 1) = Just (RealRegSingle REG_F1)
#endif
#ifdef REG_F2
-globalRegMaybe (FloatReg 2) = Just (RealReg REG_F2)
+globalRegMaybe (FloatReg 2) = Just (RealRegSingle REG_F2)
#endif
#ifdef REG_F3
-globalRegMaybe (FloatReg 3) = Just (RealReg REG_F3)
+globalRegMaybe (FloatReg 3) = Just (RealRegSingle REG_F3)
#endif
#ifdef REG_F4
-globalRegMaybe (FloatReg 4) = Just (RealReg REG_F4)
+globalRegMaybe (FloatReg 4) = Just (RealRegSingle REG_F4)
#endif
#ifdef REG_D1
-globalRegMaybe (DoubleReg 1) = Just (RealReg REG_D1)
+globalRegMaybe (DoubleReg 1) = Just (RealRegSingle REG_D1)
#endif
#ifdef REG_D2
-globalRegMaybe (DoubleReg 2) = Just (RealReg REG_D2)
+globalRegMaybe (DoubleReg 2) = Just (RealRegSingle REG_D2)
#endif
#ifdef REG_Sp
-globalRegMaybe Sp = Just (RealReg REG_Sp)
+globalRegMaybe Sp = Just (RealRegSingle REG_Sp)
#endif
#ifdef REG_Lng1
-globalRegMaybe (LongReg 1) = Just (RealReg REG_Lng1)
+globalRegMaybe (LongReg 1) = Just (RealRegSingle REG_Lng1)
#endif
#ifdef REG_Lng2
-globalRegMaybe (LongReg 2) = Just (RealReg REG_Lng2)
+globalRegMaybe (LongReg 2) = Just (RealRegSingle REG_Lng2)
#endif
#ifdef REG_SpLim
-globalRegMaybe SpLim = Just (RealReg REG_SpLim)
+globalRegMaybe SpLim = Just (RealRegSingle REG_SpLim)
#endif
#ifdef REG_Hp
-globalRegMaybe Hp = Just (RealReg REG_Hp)
+globalRegMaybe Hp = Just (RealRegSingle REG_Hp)
#endif
#ifdef REG_HpLim
-globalRegMaybe HpLim = Just (RealReg REG_HpLim)
+globalRegMaybe HpLim = Just (RealRegSingle REG_HpLim)
#endif
#ifdef REG_CurrentTSO
-globalRegMaybe CurrentTSO = Just (RealReg REG_CurrentTSO)
+globalRegMaybe CurrentTSO = Just (RealRegSingle REG_CurrentTSO)
#endif
#ifdef REG_CurrentNursery
-globalRegMaybe CurrentNursery = Just (RealReg REG_CurrentNursery)
+globalRegMaybe CurrentNursery = Just (RealRegSingle REG_CurrentNursery)
#endif
globalRegMaybe _ = Nothing
allArgRegs = panic "X86.Regs.allArgRegs: should not be used!"
#elif x86_64_TARGET_ARCH
-allArgRegs = map RealReg [rdi,rsi,rdx,rcx,r8,r9]
+allArgRegs = map regSingle [rdi,rsi,rdx,rcx,r8,r9]
#else
allArgRegs = panic "X86.Regs.allArgRegs: not defined for this architecture"
#if i386_TARGET_ARCH
-- caller-saves registers
callClobberedRegs
- = map RealReg [eax,ecx,edx,fake0,fake1,fake2,fake3,fake4,fake5]
+ = map regSingle ([eax,ecx,edx] ++ floatregnos)
#elif x86_64_TARGET_ARCH
-- all xmm regs are caller-saves
-- caller-saves registers
callClobberedRegs
- = map RealReg ([rax,rcx,rdx,rsi,rdi,r8,r9,r10,r11] ++ [16..31])
+ = map regSingle ([rax,rcx,rdx,rsi,rdi,r8,r9,r10,r11] ++ floatregnos)
#else
callClobberedRegs
#endif
+-- allocatableRegs is allMachRegNos with the fixed-use regs removed.
+-- i.e., these are the regs for which we are prepared to allow the
+-- register allocator to attempt to map VRegs to.
+allocatableRegs :: [RealReg]
+allocatableRegs
+ = let isFree i = isFastTrue (freeReg i)
+ in map RealRegSingle $ filter isFree allMachRegNos
+