[project @ 2005-05-19 07:58:35 by simonpj]
[ghc-hetmet.git] / ghc / compiler / nativeGen / MachRegs.lhs
index e94086d..61fa199 100644 (file)
@@ -41,16 +41,26 @@ module MachRegs (
        spRel,
 
 #if alpha_TARGET_ARCH
        spRel,
 
 #if alpha_TARGET_ARCH
-       allArgRegs,
        fits8Bits,
        fReg,
        gp, pv, ra, sp, t9, t10, t11, t12, v0, f0, zeroh,
 #endif
 #if i386_TARGET_ARCH
        fits8Bits,
        fReg,
        gp, pv, ra, sp, t9, t10, t11, t12, v0, f0, zeroh,
 #endif
 #if i386_TARGET_ARCH
+       EABase(..), EAIndex(..),
        eax, ebx, ecx, edx, esi, edi, ebp, esp,
        fake0, fake1, fake2, fake3, fake4, fake5,
        addrModeRegs,
 #endif
        eax, ebx, ecx, edx, esi, edi, ebp, esp,
        fake0, fake1, fake2, fake3, fake4, fake5,
        addrModeRegs,
 #endif
+#if x86_64_TARGET_ARCH
+       EABase(..), EAIndex(..), ripRel,
+       rax, rbx, rcx, rdx, rsi, rdi, rbp, rsp,
+       eax, ebx, ecx, edx, esi, edi, ebp, esp,
+       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, eax, edx,
+       addrModeRegs, allFPArgRegs,
+#endif
 #if sparc_TARGET_ARCH
        fits13Bits,
        fpRel, gReg, iReg, lReg, oReg, largeOffsetError,
 #if sparc_TARGET_ARCH
        fits13Bits,
        fpRel, gReg, iReg, lReg, oReg, largeOffsetError,
@@ -78,7 +88,6 @@ import Cmm
 import MachOp          ( MachRep(..) )
 
 import CLabel           ( CLabel, mkMainCapabilityLabel )
 import MachOp          ( MachRep(..) )
 
 import CLabel           ( CLabel, mkMainCapabilityLabel )
-import Unique          ( Unique )
 import Pretty
 import Outputable      ( Outputable(..), pprPanic, panic )
 import qualified Outputable
 import Pretty
 import Outputable      ( Outputable(..), pprPanic, panic )
 import qualified Outputable
@@ -107,6 +116,8 @@ data Imm
   | ImmIndex    CLabel Int
   | ImmFloat   Rational
   | ImmDouble  Rational
   | ImmIndex    CLabel Int
   | ImmFloat   Rational
   | ImmDouble  Rational
+  | ImmConstantSum Imm Imm
+  | ImmConstantDiff Imm Imm
 #if sparc_TARGET_ARCH
   | LO Imm                 {- Possible restrictions... -}
   | HI Imm
 #if sparc_TARGET_ARCH
   | LO Imm                 {- Possible restrictions... -}
   | HI Imm
@@ -115,10 +126,6 @@ data Imm
   | LO Imm
   | HI Imm
   | HA Imm     {- high halfword adjusted -}
   | LO Imm
   | HI Imm
   | HA Imm     {- high halfword adjusted -}
-#if darwin_TARGET_OS
-        -- special dyld (dynamic linker) things
-  | ImmDyldNonLazyPtr CLabel  -- Llabel$non_lazy_ptr
-#endif
 #endif
 strImmLit s = ImmLit (text s)
 
 #endif
 strImmLit s = ImmLit (text s)
 
@@ -128,6 +135,10 @@ litToImm (CmmFloat f F32)    = ImmFloat f
 litToImm (CmmFloat f F64)    = ImmDouble f
 litToImm (CmmLabel l)        = ImmCLbl l
 litToImm (CmmLabelOff l off) = ImmIndex l off
 litToImm (CmmFloat f F64)    = 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)
 
 -- -----------------------------------------------------------------------------
 -- Addressing modes
 
 -- -----------------------------------------------------------------------------
 -- Addressing modes
@@ -139,12 +150,12 @@ data AddrMode
   | AddrRegImm Reg Imm
 #endif
 
   | AddrRegImm Reg Imm
 #endif
 
-#if i386_TARGET_ARCH
-  = AddrBaseIndex      Base Index Displacement
+#if i386_TARGET_ARCH || x86_64_TARGET_ARCH
+  = AddrBaseIndex      EABase EAIndex Displacement
   | ImmAddr            Imm Int
 
   | ImmAddr            Imm Int
 
-type Base         = Maybe Reg
-type Index        = Maybe (Reg, Int)   -- Int is 2, 4 or 8
+data EABase       = EABaseNone  | EABaseReg Reg | EABaseRip
+data EAIndex      = EAIndexNone | EAIndex Reg Int
 type Displacement = Imm
 #endif
 
 type Displacement = Imm
 #endif
 
@@ -158,12 +169,12 @@ type Displacement = Imm
   | AddrRegImm Reg Imm
 #endif
 
   | AddrRegImm Reg Imm
 #endif
 
-#if i386_TARGET_ARCH
+#if i386_TARGET_ARCH || x86_64_TARGET_ARCH
 addrModeRegs :: AddrMode -> [Reg]
 addrModeRegs (AddrBaseIndex b i _) =  b_regs ++ i_regs
   where
 addrModeRegs :: AddrMode -> [Reg]
 addrModeRegs (AddrBaseIndex b i _) =  b_regs ++ i_regs
   where
-   b_regs = case b of { Just r -> [r]; _ -> [] }
-   i_regs = case i of { Just (r,_) -> [r]; _ -> [] }
+   b_regs = case b of { EABaseReg r -> [r]; _ -> [] }
+   i_regs = case i of { EAIndex r _ -> [r]; _ -> [] }
 addrModeRegs _ = []
 #endif
 
 addrModeRegs _ = []
 #endif
 
@@ -175,7 +186,7 @@ addrOffset addr off
 #if alpha_TARGET_ARCH
       _ -> panic "MachMisc.addrOffset not defined for Alpha"
 #endif
 #if alpha_TARGET_ARCH
       _ -> panic "MachMisc.addrOffset not defined for Alpha"
 #endif
-#if i386_TARGET_ARCH
+#if i386_TARGET_ARCH || x86_64_TARGET_ARCH
       ImmAddr i off0     -> Just (ImmAddr i (off0 + off))
 
       AddrBaseIndex r i (ImmInt n) -> Just (AddrBaseIndex r i (ImmInt (n + off)))
       ImmAddr i off0     -> Just (ImmAddr i (off0 + off))
 
       AddrBaseIndex r i (ImmInt n) -> Just (AddrBaseIndex r i (ImmInt (n + off)))
@@ -278,8 +289,10 @@ spRel :: Int       -- desired stack offset in words, positive or negative
       -> AddrMode
 
 spRel n
       -> AddrMode
 
 spRel n
-#if i386_TARGET_ARCH
-  = AddrBaseIndex (Just esp) Nothing (ImmInt (n * wORD_SIZE))
+#if defined(i386_TARGET_ARCH)
+  = AddrBaseIndex (EABaseReg esp) EAIndexNone (ImmInt (n * wORD_SIZE))
+#elif defined(x86_64_TARGET_ARCH)
+  = AddrBaseIndex (EABaseReg rsp) EAIndexNone (ImmInt (n * wORD_SIZE))
 #else
   = AddrRegImm sp (ImmInt (n * wORD_SIZE))
 #endif
 #else
   = AddrRegImm sp (ImmInt (n * wORD_SIZE))
 #endif
@@ -292,6 +305,9 @@ fpRel n
   = AddrRegImm fp (ImmInt (n * wORD_SIZE))
 #endif
 
   = AddrRegImm fp (ImmInt (n * wORD_SIZE))
 #endif
 
+#if x86_64_TARGET_ARCH
+ripRel imm = AddrBaseIndex EABaseRip EAIndexNone imm
+#endif
 
 -- -----------------------------------------------------------------------------
 -- Global registers
 
 -- -----------------------------------------------------------------------------
 -- Global registers
@@ -495,6 +511,88 @@ showReg n
 #endif
 
 {-
 #endif
 
 {-
+AMD x86_64 architecture:
+- Registers 0-16 have 32-bit counterparts (eax, ebx etc.)
+- Registers 0-7 have 16-bit counterparts (ax, bx etc.)
+- Registers 0-3 have 8 bit counterparts (ah, bh etc.)
+
+-}
+
+#if x86_64_TARGET_ARCH
+
+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
+
+ -- so we can re-use some x86 code:
+eax = rax
+ebx = rbx
+ecx = rcx
+edx = rdx
+esi = rsi
+edi = rdi
+ebp = rbp
+esp = rsp
+
+xmm n = RealReg (16+n)
+
+-- 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))
+
+regNames 
+ = ["%rax", "%rbx", "%rcx", "%rdx", "%rsi", "%rdi", "%rbp", "%rsp" ]
+
+showReg :: RegNo -> String
+showReg n
+  | n >= 16 = "%xmm" ++ show (n-16)
+  | n >= 8  = "%r" ++ show n
+  | otherwise = regNames !! n
+
+#endif
+
+{-
 The SPARC has 64 registers of interest; 32 integer registers and 32
 floating point registers.  The mapping of STG registers to SPARC
 machine registers is defined in StgRegs.h.  We are, of course,
 The SPARC has 64 registers of interest; 32 integer registers and 32
 floating point registers.  The mapping of STG registers to SPARC
 machine registers is defined in StgRegs.h.  We are, of course,
@@ -645,6 +743,42 @@ names in the header files.  Gag me with a spoon, eh?
 #define fake4 12
 #define fake5 13
 #endif
 #define fake4 12
 #define fake5 13
 #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
+#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
+
 #if sparc_TARGET_ARCH
 #define g0 0
 #define g1 1
 #if sparc_TARGET_ARCH
 #define g0 0
 #define g1 1
@@ -822,11 +956,12 @@ allMachRegNos :: [RegNo]
 allMachRegNos
    = IF_ARCH_alpha( [0..63],
      IF_ARCH_i386(  [0..13],
 allMachRegNos
    = IF_ARCH_alpha( [0..63],
      IF_ARCH_i386(  [0..13],
+     IF_ARCH_x86_64( [0..31],
      IF_ARCH_sparc( ([0..31]
                      ++ [f0,f2 .. nCG_FirstFloatReg-1]
                      ++ [nCG_FirstFloatReg .. f31]),
      IF_ARCH_powerpc([0..63],
      IF_ARCH_sparc( ([0..31]
                      ++ [f0,f2 .. nCG_FirstFloatReg-1]
                      ++ [nCG_FirstFloatReg .. f31]),
      IF_ARCH_powerpc([0..63],
-                   ))))
+                   )))))
 
 -- allocatableRegs is allMachRegNos with the fixed-use regs removed.
 -- i.e., these are the regs for which we are prepared to allow the
 
 -- allocatableRegs is allMachRegNos with the fixed-use regs removed.
 -- i.e., these are the regs for which we are prepared to allow the
@@ -852,6 +987,11 @@ callClobberedRegs
     -- caller-saves registers
     map RealReg [eax,ecx,edx,fake0,fake1,fake2,fake3,fake4,fake5]
 #endif /* i386_TARGET_ARCH */
     -- caller-saves registers
     map RealReg [eax,ecx,edx,fake0,fake1,fake2,fake3,fake4,fake5]
 #endif /* i386_TARGET_ARCH */
+#if x86_64_TARGET_ARCH
+    -- caller-saves registers
+    map RealReg ([rax,rcx,rdx,rsi,rdi,r8,r9,r10,r11] ++ [16..31])
+       -- all xmm regs are caller-saves
+#endif /* x86_64_TARGET_ARCH */
 #if sparc_TARGET_ARCH
     map RealReg 
         ( oReg 7 :
 #if sparc_TARGET_ARCH
     map RealReg 
         ( oReg 7 :
@@ -878,6 +1018,10 @@ argRegs :: RegNo -> [Reg]
 argRegs _ = panic "MachRegs.argRegs(x86): should not be used!"
 #endif
 
 argRegs _ = panic "MachRegs.argRegs(x86): should not be used!"
 #endif
 
+#if x86_64_TARGET_ARCH
+argRegs _ = panic "MachRegs.argRegs(x86_64): should not be used!"
+#endif
+
 #if alpha_TARGET_ARCH
 argRegs 0 = []
 argRegs 1 = freeMappedRegs [16, fReg 16]
 #if alpha_TARGET_ARCH
 argRegs 0 = []
 argRegs 1 = freeMappedRegs [16, fReg 16]
@@ -930,6 +1074,13 @@ allArgRegs :: [Reg]
 allArgRegs = panic "MachRegs.allArgRegs(x86): should not be used!"
 #endif
 
 allArgRegs = panic "MachRegs.allArgRegs(x86): should not be used!"
 #endif
 
+#if x86_64_TARGET_ARCH
+allArgRegs :: [Reg]
+allArgRegs = map RealReg [rdi,rsi,rdx,rcx,r8,r9]
+allFPArgRegs :: [Reg]
+allFPArgRegs = map RealReg [xmm0 .. xmm7]
+#endif
+
 #if powerpc_TARGET_ARCH
 allArgRegs :: [Reg]
 allArgRegs = map RealReg [3..10]
 #if powerpc_TARGET_ARCH
 allArgRegs :: [Reg]
 allArgRegs = map RealReg [3..10]
@@ -958,6 +1109,10 @@ freeReg 63 = fastBool False  -- always zero (f31)
 freeReg esp = fastBool False  --       %esp is the C stack pointer
 #endif
 
 freeReg esp = fastBool False  --       %esp is the C stack pointer
 #endif
 
+#if x86_64_TARGET_ARCH
+freeReg rsp = fastBool False  --       %rsp is the C stack pointer
+#endif
+
 #if sparc_TARGET_ARCH
 freeReg g0 = fastBool False  --        %g0 is always 0.
 freeReg g5 = fastBool False  --        %g5 is reserved (ABI).
 #if sparc_TARGET_ARCH
 freeReg g0 = fastBool False  --        %g0 is always 0.
 freeReg g5 = fastBool False  --        %g5 is reserved (ABI).
@@ -1086,75 +1241,75 @@ baseRegOffset _                   = panic "baseRegOffset:other"
 callerSaves :: GlobalReg -> Bool
 
 #ifdef CALLER_SAVES_Base
 callerSaves :: GlobalReg -> Bool
 
 #ifdef CALLER_SAVES_Base
-callerSaves BaseReg                    = True
+callerSaves BaseReg            = True
 #endif
 #ifdef CALLER_SAVES_R1
 #endif
 #ifdef CALLER_SAVES_R1
-callerSaves (VanillaReg _ ILIT(1))     = True
+callerSaves (VanillaReg 1)     = True
 #endif
 #ifdef CALLER_SAVES_R2
 #endif
 #ifdef CALLER_SAVES_R2
-callerSaves (VanillaReg _ ILIT(2))     = True
+callerSaves (VanillaReg 2)     = True
 #endif
 #ifdef CALLER_SAVES_R3
 #endif
 #ifdef CALLER_SAVES_R3
-callerSaves (VanillaReg _ ILIT(3))     = True
+callerSaves (VanillaReg 3)     = True
 #endif
 #ifdef CALLER_SAVES_R4
 #endif
 #ifdef CALLER_SAVES_R4
-callerSaves (VanillaReg _ ILIT(4))     = True
+callerSaves (VanillaReg 4)     = True
 #endif
 #ifdef CALLER_SAVES_R5
 #endif
 #ifdef CALLER_SAVES_R5
-callerSaves (VanillaReg _ ILIT(5))     = True
+callerSaves (VanillaReg 5)     = True
 #endif
 #ifdef CALLER_SAVES_R6
 #endif
 #ifdef CALLER_SAVES_R6
-callerSaves (VanillaReg _ ILIT(6))     = True
+callerSaves (VanillaReg 6)     = True
 #endif
 #ifdef CALLER_SAVES_R7
 #endif
 #ifdef CALLER_SAVES_R7
-callerSaves (VanillaReg _ ILIT(7))     = True
+callerSaves (VanillaReg 7)     = True
 #endif
 #ifdef CALLER_SAVES_R8
 #endif
 #ifdef CALLER_SAVES_R8
-callerSaves (VanillaReg _ ILIT(8))     = True
+callerSaves (VanillaReg 8)     = True
 #endif
 #ifdef CALLER_SAVES_F1
 #endif
 #ifdef CALLER_SAVES_F1
-callerSaves (FloatReg 1#)              = True
+callerSaves (FloatReg 1)       = True
 #endif
 #ifdef CALLER_SAVES_F2
 #endif
 #ifdef CALLER_SAVES_F2
-callerSaves (FloatReg 2#)              = True
+callerSaves (FloatReg 2)       = True
 #endif
 #ifdef CALLER_SAVES_F3
 #endif
 #ifdef CALLER_SAVES_F3
-callerSaves (FloatReg 3#)              = True
+callerSaves (FloatReg 3)       = True
 #endif
 #ifdef CALLER_SAVES_F4
 #endif
 #ifdef CALLER_SAVES_F4
-callerSaves (FloatReg 4#)              = True
+callerSaves (FloatReg 4)       = True
 #endif
 #ifdef CALLER_SAVES_D1
 #endif
 #ifdef CALLER_SAVES_D1
-callerSaves (DoubleReg 1#)             = True
+callerSaves (DoubleReg 1)      = True
 #endif
 #ifdef CALLER_SAVES_D2
 #endif
 #ifdef CALLER_SAVES_D2
-callerSaves (DoubleReg 2#)             = True
+callerSaves (DoubleReg 2)      = True
 #endif
 #ifdef CALLER_SAVES_L1
 #endif
 #ifdef CALLER_SAVES_L1
-callerSaves (LongReg _ ILIT(1))                = True
+callerSaves (LongReg 1)                = True
 #endif
 #ifdef CALLER_SAVES_Sp
 #endif
 #ifdef CALLER_SAVES_Sp
-callerSaves Sp                         = True
+callerSaves Sp                 = True
 #endif
 #ifdef CALLER_SAVES_SpLim
 #endif
 #ifdef CALLER_SAVES_SpLim
-callerSaves SpLim                      = True
+callerSaves SpLim              = True
 #endif
 #ifdef CALLER_SAVES_Hp
 #endif
 #ifdef CALLER_SAVES_Hp
-callerSaves Hp                         = True
+callerSaves Hp                 = True
 #endif
 #ifdef CALLER_SAVES_HpLim
 #endif
 #ifdef CALLER_SAVES_HpLim
-callerSaves HpLim                      = True
+callerSaves HpLim              = True
 #endif
 #ifdef CALLER_SAVES_CurrentTSO
 #endif
 #ifdef CALLER_SAVES_CurrentTSO
-callerSaves CurrentTSO                 = True
+callerSaves CurrentTSO         = True
 #endif
 #ifdef CALLER_SAVES_CurrentNursery
 #endif
 #ifdef CALLER_SAVES_CurrentNursery
-callerSaves CurrentNursery             = True
+callerSaves CurrentNursery     = True
 #endif
 #endif
-callerSaves _                          = False
+callerSaves _                  = False
 
 
 
 
--- | Returns 'Nothing' if this global register is not stored
+--  | Returns 'Nothing' if this global register is not stored
 -- in a real machine register, otherwise returns @'Just' reg@, where
 -- reg is the machine register it is stored in.
 
 -- in a real machine register, otherwise returns @'Just' reg@, where
 -- reg is the machine register it is stored in.