X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=ghc%2Fcompiler%2FnativeGen%2FMachRegs.lhs;h=ef3086bbc3f97421c3192234d1222ad58fefb3f1;hb=db5031360e21a654c6457f71df60af26ac205f44;hp=ec28f70075d3cec0e2c1176682d407b75190b475;hpb=b4d045ae655e5eae25b88917cfe75d7dc7689c21;p=ghc-hetmet.git diff --git a/ghc/compiler/nativeGen/MachRegs.lhs b/ghc/compiler/nativeGen/MachRegs.lhs index ec28f70..ef3086b 100644 --- a/ghc/compiler/nativeGen/MachRegs.lhs +++ b/ghc/compiler/nativeGen/MachRegs.lhs @@ -33,7 +33,7 @@ module MachRegs ( -- * Global registers get_GlobalReg_reg_or_addr, - callerSaves, + callerSaves, callerSaveVolatileRegs, -- * Machine-dependent register-related stuff allocatableRegs, argRegs, allArgRegs, callClobberedRegs, @@ -41,16 +41,26 @@ module MachRegs ( 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, + addrModeRegs, allFPArgRegs, +#endif #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 Unique ( Unique ) import Pretty import Outputable ( Outputable(..), pprPanic, panic ) import qualified Outputable @@ -141,12 +150,12 @@ data AddrMode | 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 @@ -160,12 +169,12 @@ type Displacement = Imm | 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 @@ -177,7 +186,7 @@ addrOffset addr off #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))) @@ -280,8 +289,10 @@ spRel :: Int -- desired stack offset in words, positive or negative -> 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 @@ -294,6 +305,9 @@ fpRel n = AddrRegImm fp (ImmInt (n * wORD_SIZE)) #endif +#if x86_64_TARGET_ARCH +ripRel imm = AddrBaseIndex EABaseRip EAIndexNone imm +#endif -- ----------------------------------------------------------------------------- -- Global registers @@ -328,6 +342,39 @@ get_Regtable_addr_from_offset rep offset 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 @@ -380,6 +427,9 @@ instance Uniquable Reg where 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 @@ -497,6 +547,88 @@ showReg n #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, @@ -647,6 +779,42 @@ names in the header files. Gag me with a spoon, eh? #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 @@ -824,11 +992,12 @@ allMachRegNos :: [RegNo] 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 @@ -854,6 +1023,11 @@ callClobberedRegs -- 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 : @@ -880,6 +1054,10 @@ argRegs :: RegNo -> [Reg] 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] @@ -932,6 +1110,13 @@ allArgRegs :: [Reg] 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] @@ -960,6 +1145,10 @@ freeReg 63 = fastBool False -- always zero (f31) 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). @@ -1088,75 +1277,75 @@ baseRegOffset _ = panic "baseRegOffset:other" 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.