-- * Global registers
get_GlobalReg_reg_or_addr,
- callerSaves,
+ callerSaves, callerSaveVolatileRegs,
-- * Machine-dependent register-related stuff
allocatableRegs, argRegs, allArgRegs, callClobberedRegs,
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,
import MachOp ( MachRep(..) )
import CLabel ( CLabel, mkMainCapabilityLabel )
-import Unique ( Unique )
import Pretty
import Outputable ( Outputable(..), pprPanic, panic )
import qualified Outputable
#endif
#if i386_TARGET_ARCH || x86_64_TARGET_ARCH
- = AddrBaseIndex Base Index Displacement
+ = 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
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
spRel n
#if defined(i386_TARGET_ARCH)
- = AddrBaseIndex (Just esp) Nothing (ImmInt (n * wORD_SIZE))
+ = AddrBaseIndex (EABaseReg esp) EAIndexNone (ImmInt (n * wORD_SIZE))
#elif defined(x86_64_TARGET_ARCH)
- = AddrBaseIndex (Just rsp) Nothing (ImmInt (n * wORD_SIZE))
+ = 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
Nothing -> regTableOffset offset
Just _ -> CmmRegOff (CmmGlobal BaseReg) offset
+-- -----------------------------------------------------------------------------
+-- caller-save registers
+
+-- Here we generate the sequence of saves/restores required around a
+-- foreign call instruction.
+
+callerSaveVolatileRegs :: Maybe [GlobalReg] -> ([CmmStmt], [CmmStmt])
+callerSaveVolatileRegs vols = (caller_save, caller_load)
+ where
+ caller_save = foldr ($!) [] (map callerSaveGlobalReg regs_to_save)
+ caller_load = foldr ($!) [] (map callerRestoreGlobalReg regs_to_save)
+
+ system_regs = [Sp,SpLim,Hp,HpLim,CurrentTSO,CurrentNursery,
+ {-SparkHd,SparkTl,SparkBase,SparkLim,-}BaseReg ]
+
+ regs_to_save = system_regs ++ vol_list
+
+ vol_list = case vols of Nothing -> []; Just regs -> regs
+
+ callerSaveGlobalReg reg next
+ | callerSaves reg =
+ CmmStore (get_GlobalReg_addr reg)
+ (CmmReg (CmmGlobal reg)) : next
+ | otherwise = next
+
+ callerRestoreGlobalReg reg next
+ | callerSaves reg =
+ CmmAssign (CmmGlobal reg)
+ (CmmLoad (get_GlobalReg_addr reg) (globalRegRep reg))
+ : next
+ | otherwise = next
+
+
-- ---------------------------------------------------------------------------
-- Registers
getUnique (VirtualRegF u) = u
getUnique (VirtualRegD u) = u
+unRealReg (RealReg i) = i
+unRealReg vreg = pprPanic "unRealReg on VirtualReg" (ppr vreg)
+
mkVReg :: Unique -> MachRep -> Reg
mkVReg u rep
= case rep of
showReg :: RegNo -> String
showReg n
- | n >= 16 = "%xmm" ++ show n
+ | n >= 16 = "%xmm" ++ show (n-16)
| n >= 8 = "%r" ++ show n
| otherwise = regNames !! n
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