spRel,
#if alpha_TARGET_ARCH
- allArgRegs,
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
+#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,
import MachOp ( MachRep(..) )
import CLabel ( CLabel, mkMainCapabilityLabel )
-import Unique ( Unique )
import Pretty
import Outputable ( Outputable(..), pprPanic, panic )
import qualified Outputable
| ImmIndex CLabel Int
| ImmFloat Rational
| ImmDouble Rational
+ | ImmConstantSum Imm Imm
+ | ImmConstantDiff Imm Imm
#if sparc_TARGET_ARCH
| LO Imm {- Possible restrictions... -}
| HI Imm
| 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)
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
| 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
-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
| 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
- 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
#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)))
-> 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
= AddrRegImm fp (ImmInt (n * wORD_SIZE))
#endif
+#if x86_64_TARGET_ARCH
+ripRel imm = AddrBaseIndex EABaseRip EAIndexNone imm
+#endif
-- -----------------------------------------------------------------------------
-- Global registers
#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,
#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
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],
- ))))
+ )))))
-- allocatableRegs is allMachRegNos with the fixed-use regs removed.
-- i.e., these are the regs for which we are prepared to allow the
-- 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 :
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]
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]
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).
callerSaves :: GlobalReg -> Bool
#ifdef CALLER_SAVES_Base
-callerSaves BaseReg = True
+callerSaves BaseReg = True
#endif
#ifdef CALLER_SAVES_R1
-callerSaves (VanillaReg _ ILIT(1)) = True
+callerSaves (VanillaReg 1) = True
#endif
#ifdef CALLER_SAVES_R2
-callerSaves (VanillaReg _ ILIT(2)) = True
+callerSaves (VanillaReg 2) = True
#endif
#ifdef CALLER_SAVES_R3
-callerSaves (VanillaReg _ ILIT(3)) = True
+callerSaves (VanillaReg 3) = True
#endif
#ifdef CALLER_SAVES_R4
-callerSaves (VanillaReg _ ILIT(4)) = True
+callerSaves (VanillaReg 4) = True
#endif
#ifdef CALLER_SAVES_R5
-callerSaves (VanillaReg _ ILIT(5)) = True
+callerSaves (VanillaReg 5) = True
#endif
#ifdef CALLER_SAVES_R6
-callerSaves (VanillaReg _ ILIT(6)) = True
+callerSaves (VanillaReg 6) = True
#endif
#ifdef CALLER_SAVES_R7
-callerSaves (VanillaReg _ ILIT(7)) = True
+callerSaves (VanillaReg 7) = True
#endif
#ifdef CALLER_SAVES_R8
-callerSaves (VanillaReg _ ILIT(8)) = True
+callerSaves (VanillaReg 8) = True
#endif
#ifdef CALLER_SAVES_F1
-callerSaves (FloatReg 1#) = True
+callerSaves (FloatReg 1) = True
#endif
#ifdef CALLER_SAVES_F2
-callerSaves (FloatReg 2#) = True
+callerSaves (FloatReg 2) = True
#endif
#ifdef CALLER_SAVES_F3
-callerSaves (FloatReg 3#) = True
+callerSaves (FloatReg 3) = True
#endif
#ifdef CALLER_SAVES_F4
-callerSaves (FloatReg 4#) = True
+callerSaves (FloatReg 4) = True
#endif
#ifdef CALLER_SAVES_D1
-callerSaves (DoubleReg 1#) = True
+callerSaves (DoubleReg 1) = True
#endif
#ifdef CALLER_SAVES_D2
-callerSaves (DoubleReg 2#) = True
+callerSaves (DoubleReg 2) = True
#endif
#ifdef CALLER_SAVES_L1
-callerSaves (LongReg _ ILIT(1)) = True
+callerSaves (LongReg 1) = True
#endif
#ifdef CALLER_SAVES_Sp
-callerSaves Sp = True
+callerSaves Sp = True
#endif
#ifdef CALLER_SAVES_SpLim
-callerSaves SpLim = True
+callerSaves SpLim = True
#endif
#ifdef CALLER_SAVES_Hp
-callerSaves Hp = True
+callerSaves Hp = True
#endif
#ifdef CALLER_SAVES_HpLim
-callerSaves HpLim = True
+callerSaves HpLim = True
#endif
#ifdef CALLER_SAVES_CurrentTSO
-callerSaves CurrentTSO = True
+callerSaves CurrentTSO = True
#endif
#ifdef CALLER_SAVES_CurrentNursery
-callerSaves CurrentNursery = True
+callerSaves CurrentNursery = True
#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.