NCG: Fix off-by-one error in realRegSqueeze
[ghc-hetmet.git] / compiler / nativeGen / X86 / Regs.hs
index 3432090..943a7a3 100644 (file)
@@ -1,14 +1,7 @@
 module X86.Regs (
 module X86.Regs (
-
-       -- sizes
-       Size(..),
-       intSize, 
-       floatSize, 
-       isFloatSize, 
-       wordSize,
-       cmmTypeSize,
-       sizeToWidth,
-       mkVReg,
+       -- squeese functions for the graph allocator
+       virtualRegSqueeze,
+       realRegSqueeze,
 
        -- immediates
        Imm(..),
 
        -- immediates
        Imm(..),
@@ -25,33 +18,29 @@ module X86.Regs (
        allArgRegs,
        callClobberedRegs,
        allMachRegNos,
        allArgRegs,
        callClobberedRegs,
        allMachRegNos,
-       regClass,
+       classOfRealReg,
        showReg,        
 
        -- machine specific
        EABase(..), EAIndex(..), addrModeRegs,
 
        showReg,        
 
        -- machine specific
        EABase(..), EAIndex(..), addrModeRegs,
 
-#if i386_TARGET_ARCH
-       -- part of address mode. shared for both arches.
        eax, ebx, ecx, edx, esi, edi, ebp, esp,
        eax, ebx, ecx, edx, esi, edi, ebp, esp,
-       fake0, fake1, fake2, fake3, fake4, fake5,
-#endif
-#if x86_64_TARGET_ARCH
-       -- part of address mode. shared for both arches.
-       ripRel,
-       allFPArgRegs,
-       
+       fake0, fake1, fake2, fake3, fake4, fake5, firstfake,
+
        rax, rbx, rcx, rdx, rsi, rdi, rbp, rsp,
        rax, rbx, rcx, rdx, rsi, rdi, rbp, rsp,
-       eax, ebx, ecx, edx, esi, edi, ebp, esp,
-       r8, r9, r10, r11, r12, r13, r14, r15,
+       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,
        xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7,
        xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15,
        xmm,
-#endif
+
+       ripRel,
+       allFPArgRegs,
 
        -- horror show
        freeReg,
 
        -- horror show
        freeReg,
-       globalRegMaybe
+       globalRegMaybe,
+       
+       allocatableRegs
 )
 
 where
 )
 
 where
@@ -59,96 +48,80 @@ where
 #include "nativeGen/NCG.h"
 #include "HsVersions.h"
 
 #include "nativeGen/NCG.h"
 #include "HsVersions.h"
 
-#if i386_TARGET_ARCH
-# define STOLEN_X86_REGS 4
--- HACK: go for the max
-#endif
-
-#include "../includes/MachRegs.h"
+#include "../includes/stg/MachRegs.h"
 
 
-import RegsBase
+import Reg
+import RegClass
 
 import BlockId
 import Cmm
 import CLabel           ( CLabel )
 import Pretty
 
 import BlockId
 import Cmm
 import CLabel           ( CLabel )
 import Pretty
-import Outputable      ( Outputable(..), pprPanic, panic )
-import qualified Outputable
-import Unique
+import Outputable      ( panic )
+import FastTypes
 import FastBool
 
 import FastBool
 
--- -----------------------------------------------------------------------------
--- 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.
---
--- 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"
 
 
+#if  defined(i386_TARGET_ARCH) || defined(x86_64_TARGET_ARCH)
+import Constants
+#endif
 
 
-mkVReg :: Unique -> Size -> Reg
-mkVReg u size
-   | not (isFloatSize size) = VirtualRegI u
-   | otherwise
-   = case size of
-        FF32   -> VirtualRegD u
-        FF64   -> VirtualRegD u
-       _       -> panic "mkVReg"
 
 
+-- | 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.
+--
+{-# 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
 
 -- -----------------------------------------------------------------------------
 -- Immediates
@@ -243,129 +216,83 @@ spRel _  = panic "X86.Regs.spRel: not defined for this architecture"
 
 #endif
 
 
 #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.
 
 
--- 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.
--- Sparc passes up to the first 6 args in regs.
--- Dunno about Alpha.
-argRegs :: RegNo -> [Reg]
-argRegs _      = panic "MachRegs.argRegs(x86): should not be used!"
-
-
-
--- 
-allArgRegs :: [Reg]
-
-#if   i386_TARGET_ARCH
-allArgRegs = panic "X86.Regs.allArgRegs: should not be used!"
-
-#elif x86_64_TARGET_ARCH
-allArgRegs = map RealReg [rdi,rsi,rdx,rcx,r8,r9]
+firstfake, lastfake :: RegNo
+firstfake = 16
+lastfake  = 21
 
 
+firstxmm, lastxmm :: RegNo
+firstxmm  = 24
+#if i386_TARGET_ARCH
+lastxmm   = 31
 #else
 #else
-allArgRegs  = panic "X86.Regs.allArgRegs: not defined for this architecture"
+lastxmm   = 39
 #endif
 
 #endif
 
-
--- | these are the regs which we cannot assume stay alive over a C call.  
-callClobberedRegs :: [Reg]
-
-#if   i386_TARGET_ARCH
--- caller-saves registers
-callClobberedRegs
-  = map RealReg [eax,ecx,edx,fake0,fake1,fake2,fake3,fake4,fake5]
-
-#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])
-
+lastint :: RegNo
+#if i386_TARGET_ARCH
+lastint = 7 -- not %r8..%r15
 #else
 #else
-callClobberedRegs
-  = panic "X86.Regs.callClobberedRegs: not defined for this architecture"
+lastint = 15
 #endif
 
 #endif
 
+intregnos, fakeregnos, xmmregnos, floatregnos :: [RegNo]
+intregnos   = [0..lastint]
+fakeregnos  = [firstfake .. lastfake]
+xmmregnos   = [firstxmm  .. lastxmm]
+floatregnos = fakeregnos ++ xmmregnos;
 
 
--- | 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
+-- 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.
+-- Sparc passes up to the first 6 args in regs.
+-- Dunno about Alpha.
+argRegs :: RegNo -> [Reg]
+argRegs _      = panic "MachRegs.argRegs(x86): should not be used!"
 
 
+-- | The complete set of machine registers.
+allMachRegNos :: [RegNo]
+allMachRegNos  = intregnos ++ floatregnos
 
 -- | Take the class of a register.
 
 -- | 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  u) = RcInteger
-regClass (VirtualRegHi u) = RcInteger
-regClass (VirtualRegD  u) = RcDouble
-regClass (VirtualRegF  u) = pprPanic "regClass(x86):VirtualRegF" 
-                                    (ppr (VirtualRegF 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).
 -- 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  u) = RcInteger
-regClass (VirtualRegHi u) = RcInteger
-regClass (VirtualRegD  u) = RcDouble
-regClass (VirtualRegF  u) = pprPanic "regClass(x86_64):VirtualRegF" 
-                                    (ppr (VirtualRegF 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
 
 -- | Get the name of the register with this number.
 showReg :: RegNo -> String
-
-#if   i386_TARGET_ARCH
 showReg n
 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 
 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
 #elif x86_64_TARGET_ARCH
-showReg n
-       | n >= 16       = "%xmm" ++ show (n-16)
-       | n >= 8        = "%r" ++ show n
-       | otherwise     = regNames !! n
-
-regNames 
- = ["%rax", "%rbx", "%rcx", "%rdx", "%rsi", "%rdi", "%rbp", "%rsp" ]
-
+   = ["%rax", "%rbx", "%rcx", "%rdx", "%rsi", "%rdi", "%rbp", "%rsp" ]
 #else
 #else
-showReg _      = panic "X86.Regs.showReg: not defined for this architecture"
-
+   = []
 #endif
 
 
 
 #endif
 
 
 
-
 -- machine specific ------------------------------------------------------------
 
 
 -- machine specific ------------------------------------------------------------
 
 
@@ -375,7 +302,7 @@ Intel x86 architecture:
 - 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.)
 - 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.
 
   fp registers, and 3-operand insns for them, and we translate this into
   real stack-based x86 fp code after register allocation.
 
@@ -384,25 +311,24 @@ regs.  @regClass@ barfs if you give it a VirtualRegF, and mkVReg above should
 never generate them.
 -}
 
 never generate them.
 -}
 
-#if   i386_TARGET_ARCH
 fake0, fake1, fake2, fake3, fake4, fake5, 
        eax, ebx, ecx, edx, esp, ebp, esi, edi :: Reg
 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
 
 
-#endif
+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
+
 
 
 {-
 
 
 {-
@@ -413,52 +339,53 @@ AMD x86_64 architecture:
 
 -}
 
 
 -}
 
-#if   x86_64_TARGET_ARCH
-allFPArgRegs :: [Reg]
-allFPArgRegs   = map RealReg [xmm0 .. xmm7]
-
-ripRel imm     = AddrBaseIndex EABaseRip EAIndexNone imm
-
-
 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, 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   = 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 regSingle [firstxmm .. firstxmm+7]
+
+ripRel :: Displacement -> AddrMode
+ripRel imm     = AddrBaseIndex EABaseRip EAIndexNone imm
+
 
  -- so we can re-use some x86 code:
 
  -- so we can re-use some x86 code:
+{-
 eax = rax
 ebx = rbx
 ecx = rcx
 eax = rax
 ebx = rbx
 ecx = rcx
@@ -467,16 +394,19 @@ esi = rsi
 edi = rdi
 ebp = rbp
 esp = rsp
 edi = rdi
 ebp = rbp
 esp = rsp
+-}
 
 
-xmm n = RealReg (16+n)
+xmm :: RegNo -> Reg
+xmm n = regSingle (firstxmm+n)
 
 
-#endif
 
 
 
 -- horror show -----------------------------------------------------------------
 
 
 
 -- horror show -----------------------------------------------------------------
-freeReg :: RegNo -> FastBool
-globalRegMaybe :: GlobalReg -> Maybe Reg
+freeReg                :: RegNo -> FastBool
+globalRegMaybe                 :: GlobalReg -> Maybe RealReg
+allArgRegs             :: [Reg]
+callClobberedRegs      :: [Reg]
 
 #if defined(i386_TARGET_ARCH) || defined(x86_64_TARGET_ARCH)
 
 
 #if defined(i386_TARGET_ARCH) || defined(x86_64_TARGET_ARCH)
 
@@ -489,12 +419,6 @@ globalRegMaybe :: GlobalReg -> Maybe Reg
 #define edi 5
 #define ebp 6
 #define esp 7
 #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
 #endif
 
 #if x86_64_TARGET_ARCH
@@ -514,25 +438,31 @@ globalRegMaybe :: GlobalReg -> Maybe Reg
 #define r13   13
 #define r14   14
 #define r15   15
 #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
 
 #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
 
 #if i386_TARGET_ARCH
 freeReg esp = fastBool False  --       %esp is the C stack pointer
@@ -602,7 +532,7 @@ freeReg REG_Hp   = fastBool False
 #ifdef REG_HpLim
 freeReg REG_HpLim = fastBool False
 #endif
 #ifdef REG_HpLim
 freeReg REG_HpLim = fastBool False
 #endif
-freeReg n               = fastBool True
+freeReg _               = fastBool True
 
 
 --  | Returns 'Nothing' if this global register is not stored
 
 
 --  | Returns 'Nothing' if this global register is not stored
@@ -610,85 +540,132 @@ freeReg n               = fastBool True
 -- reg is the machine register it is stored in.
 
 #ifdef REG_Base
 -- 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
 #endif
 #ifdef REG_R1
-globalRegMaybe (VanillaReg 1 _)                = Just (RealReg REG_R1)
+globalRegMaybe (VanillaReg 1 _)                = Just (RealRegSingle REG_R1)
 #endif 
 #ifdef REG_R2 
 #endif 
 #ifdef REG_R2 
-globalRegMaybe (VanillaReg 2 _)                = Just (RealReg REG_R2)
+globalRegMaybe (VanillaReg 2 _)                = Just (RealRegSingle REG_R2)
 #endif 
 #ifdef REG_R3 
 #endif 
 #ifdef REG_R3 
-globalRegMaybe (VanillaReg 3 _)        = Just (RealReg REG_R3)
+globalRegMaybe (VanillaReg 3 _)        = Just (RealRegSingle REG_R3)
 #endif 
 #ifdef REG_R4 
 #endif 
 #ifdef REG_R4 
-globalRegMaybe (VanillaReg 4 _)                = Just (RealReg REG_R4)
+globalRegMaybe (VanillaReg 4 _)                = Just (RealRegSingle REG_R4)
 #endif 
 #ifdef REG_R5 
 #endif 
 #ifdef REG_R5 
-globalRegMaybe (VanillaReg 5 _)                = Just (RealReg REG_R5)
+globalRegMaybe (VanillaReg 5 _)                = Just (RealRegSingle REG_R5)
 #endif 
 #ifdef REG_R6 
 #endif 
 #ifdef REG_R6 
-globalRegMaybe (VanillaReg 6 _)                = Just (RealReg REG_R6)
+globalRegMaybe (VanillaReg 6 _)                = Just (RealRegSingle REG_R6)
 #endif 
 #ifdef REG_R7 
 #endif 
 #ifdef REG_R7 
-globalRegMaybe (VanillaReg 7 _)                = Just (RealReg REG_R7)
+globalRegMaybe (VanillaReg 7 _)                = Just (RealRegSingle REG_R7)
 #endif 
 #ifdef REG_R8 
 #endif 
 #ifdef REG_R8 
-globalRegMaybe (VanillaReg 8 _)                = Just (RealReg REG_R8)
+globalRegMaybe (VanillaReg 8 _)                = Just (RealRegSingle REG_R8)
 #endif
 #ifdef REG_R9 
 #endif
 #ifdef REG_R9 
-globalRegMaybe (VanillaReg 9 _)                = Just (RealReg REG_R9)
+globalRegMaybe (VanillaReg 9 _)                = Just (RealRegSingle REG_R9)
 #endif
 #ifdef REG_R10 
 #endif
 #ifdef REG_R10 
-globalRegMaybe (VanillaReg 10 _)       = Just (RealReg REG_R10)
+globalRegMaybe (VanillaReg 10 _)       = Just (RealRegSingle REG_R10)
 #endif
 #ifdef REG_F1
 #endif
 #ifdef REG_F1
-globalRegMaybe (FloatReg 1)            = Just (RealReg REG_F1)
+globalRegMaybe (FloatReg 1)            = Just (RealRegSingle REG_F1)
 #endif                                 
 #ifdef REG_F2                          
 #endif                                 
 #ifdef REG_F2                          
-globalRegMaybe (FloatReg 2)            = Just (RealReg REG_F2)
+globalRegMaybe (FloatReg 2)            = Just (RealRegSingle REG_F2)
 #endif                                 
 #ifdef REG_F3                          
 #endif                                 
 #ifdef REG_F3                          
-globalRegMaybe (FloatReg 3)            = Just (RealReg REG_F3)
+globalRegMaybe (FloatReg 3)            = Just (RealRegSingle REG_F3)
 #endif                                 
 #ifdef REG_F4                          
 #endif                                 
 #ifdef REG_F4                          
-globalRegMaybe (FloatReg 4)            = Just (RealReg REG_F4)
+globalRegMaybe (FloatReg 4)            = Just (RealRegSingle REG_F4)
 #endif                                 
 #ifdef REG_D1                          
 #endif                                 
 #ifdef REG_D1                          
-globalRegMaybe (DoubleReg 1)           = Just (RealReg REG_D1)
+globalRegMaybe (DoubleReg 1)           = Just (RealRegSingle REG_D1)
 #endif                                 
 #ifdef REG_D2                          
 #endif                                 
 #ifdef REG_D2                          
-globalRegMaybe (DoubleReg 2)           = Just (RealReg REG_D2)
+globalRegMaybe (DoubleReg 2)           = Just (RealRegSingle REG_D2)
 #endif
 #ifdef REG_Sp      
 #endif
 #ifdef REG_Sp      
-globalRegMaybe Sp                      = Just (RealReg REG_Sp)
+globalRegMaybe Sp                      = Just (RealRegSingle REG_Sp)
 #endif
 #ifdef REG_Lng1                                
 #endif
 #ifdef REG_Lng1                                
-globalRegMaybe (LongReg 1)             = Just (RealReg REG_Lng1)
+globalRegMaybe (LongReg 1)             = Just (RealRegSingle REG_Lng1)
 #endif                                 
 #ifdef REG_Lng2                                
 #endif                                 
 #ifdef REG_Lng2                                
-globalRegMaybe (LongReg 2)             = Just (RealReg REG_Lng2)
+globalRegMaybe (LongReg 2)             = Just (RealRegSingle REG_Lng2)
 #endif
 #ifdef REG_SpLim                               
 #endif
 #ifdef REG_SpLim                               
-globalRegMaybe SpLim                   = Just (RealReg REG_SpLim)
+globalRegMaybe SpLim                   = Just (RealRegSingle REG_SpLim)
 #endif                                 
 #ifdef REG_Hp                          
 #endif                                 
 #ifdef REG_Hp                          
-globalRegMaybe Hp                      = Just (RealReg REG_Hp)
+globalRegMaybe Hp                      = Just (RealRegSingle REG_Hp)
 #endif                                 
 #ifdef REG_HpLim                       
 #endif                                 
 #ifdef REG_HpLim                       
-globalRegMaybe HpLim                   = Just (RealReg REG_HpLim)
+globalRegMaybe HpLim                   = Just (RealRegSingle REG_HpLim)
 #endif                                 
 #ifdef REG_CurrentTSO                          
 #endif                                 
 #ifdef REG_CurrentTSO                          
-globalRegMaybe CurrentTSO              = Just (RealReg REG_CurrentTSO)
+globalRegMaybe CurrentTSO              = Just (RealRegSingle REG_CurrentTSO)
 #endif                                 
 #ifdef REG_CurrentNursery                              
 #endif                                 
 #ifdef REG_CurrentNursery                              
-globalRegMaybe CurrentNursery          = Just (RealReg REG_CurrentNursery)
+globalRegMaybe CurrentNursery          = Just (RealRegSingle REG_CurrentNursery)
 #endif                                 
 globalRegMaybe _                       = Nothing
 
 #endif                                 
 globalRegMaybe _                       = Nothing
 
+-- 
+
+#if   i386_TARGET_ARCH
+allArgRegs = panic "X86.Regs.allArgRegs: should not be used!"
+
+#elif x86_64_TARGET_ARCH
+allArgRegs = map regSingle [rdi,rsi,rdx,rcx,r8,r9]
+
+#else
+allArgRegs  = panic "X86.Regs.allArgRegs: not defined for this architecture"
+#endif
+
+
+-- | these are the regs which we cannot assume stay alive over a C call.  
+
+#if   i386_TARGET_ARCH
+-- caller-saves registers
+callClobberedRegs
+  = map regSingle ([eax,ecx,edx]  ++ floatregnos)
+
+#elif x86_64_TARGET_ARCH
+-- all xmm regs are caller-saves
+-- caller-saves registers
+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 */
 
 #else /* i386_TARGET_ARCH || x86_64_TARGET_ARCH */
 
+
+
 freeReg        _               = 0#
 globalRegMaybe _       = panic "X86.Regs.globalRegMaybe: not defined"
 
 freeReg        _               = 0#
 globalRegMaybe _       = panic "X86.Regs.globalRegMaybe: not defined"
 
+allArgRegs             = panic "X86.Regs.globalRegMaybe: not defined"
+callClobberedRegs      = panic "X86.Regs.globalRegMaybe: not defined"
+
+
 #endif
 #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
+
+