1 -- -----------------------------------------------------------------------------
3 -- (c) The University of Glasgow 1994-2004
5 -- -----------------------------------------------------------------------------
31 sp, r3, r4, r27, r28, f1, f20, f21,
36 get_GlobalReg_reg_or_addr,
43 #include "nativeGen/NCG.h"
44 #include "HsVersions.h"
45 #include "../includes/MachRegs.h"
50 import CgUtils ( get_GlobalReg_addr )
53 import CLabel ( CLabel )
55 import Outputable ( Outputable(..), pprPanic, panic )
56 import qualified Outputable
60 import Data.Word ( Word8, Word16, Word32 )
61 import Data.Int ( Int8, Int16, Int32 )
64 -- immediates ------------------------------------------------------------------
67 | ImmInteger Integer -- Sigh.
68 | ImmCLbl CLabel -- AbstractC Label (with baggage)
69 | ImmLit Doc -- Simple string
73 | ImmConstantSum Imm Imm
74 | ImmConstantDiff Imm Imm
77 | HA Imm {- high halfword adjusted -}
80 strImmLit :: String -> Imm
81 strImmLit s = ImmLit (text s)
84 litToImm :: CmmLit -> Imm
85 litToImm (CmmInt i w) = ImmInteger (narrowS w i)
86 -- narrow to the width: a CmmInt might be out of
87 -- range, but we assume that ImmInteger only contains
88 -- in-range values. A signed value should be fine here.
89 litToImm (CmmFloat f W32) = ImmFloat f
90 litToImm (CmmFloat f W64) = ImmDouble f
91 litToImm (CmmLabel l) = ImmCLbl l
92 litToImm (CmmLabelOff l off) = ImmIndex l off
93 litToImm (CmmLabelDiffOff l1 l2 off)
95 (ImmConstantDiff (ImmCLbl l1) (ImmCLbl l2))
97 litToImm (CmmBlock id) = ImmCLbl (infoTblLbl id)
98 litToImm _ = panic "PPC.Regs.litToImm: no match"
101 -- addressing modes ------------------------------------------------------------
108 addrOffset :: AddrMode -> Int -> Maybe AddrMode
111 AddrRegImm r (ImmInt n)
112 | fits16Bits n2 -> Just (AddrRegImm r (ImmInt n2))
113 | otherwise -> Nothing
116 AddrRegImm r (ImmInteger n)
117 | fits16Bits n2 -> Just (AddrRegImm r (ImmInt (fromInteger n2)))
118 | otherwise -> Nothing
119 where n2 = n + toInteger off
124 -- registers -------------------------------------------------------------------
125 -- @spRel@ gives us a stack relative addressing mode for volatile
126 -- temporaries and for excess call arguments. @fpRel@, where
127 -- applicable, is the same but for the frame pointer.
129 spRel :: Int -- desired stack offset in words, positive or negative
132 spRel n = AddrRegImm sp (ImmInt (n * wORD_SIZE))
135 -- argRegs is the set of regs which are read for an n-argument call to C.
136 -- For archs which pass all args on the stack (x86), is empty.
137 -- Sparc passes up to the first 6 args in regs.
138 -- Dunno about Alpha.
139 argRegs :: RegNo -> [Reg]
141 argRegs 1 = map RealReg [3]
142 argRegs 2 = map RealReg [3,4]
143 argRegs 3 = map RealReg [3..5]
144 argRegs 4 = map RealReg [3..6]
145 argRegs 5 = map RealReg [3..7]
146 argRegs 6 = map RealReg [3..8]
147 argRegs 7 = map RealReg [3..9]
148 argRegs 8 = map RealReg [3..10]
149 argRegs _ = panic "MachRegs.argRegs(powerpc): don't know about >8 arguments!"
153 allArgRegs = map RealReg [3..10]
156 -- these are the regs which we cannot assume stay alive over a C call.
157 callClobberedRegs :: [Reg]
158 #if defined(darwin_TARGET_OS)
160 = map RealReg (0:[2..12] ++ map fReg [0..13])
162 #elif defined(linux_TARGET_OS)
164 = map RealReg (0:[2..13] ++ map fReg [0..13])
168 = panic "PPC.Regs.callClobberedRegs: not defined for this architecture"
172 allMachRegNos :: [RegNo]
173 allMachRegNos = [0..63]
176 {-# INLINE regClass #-}
177 regClass :: Reg -> RegClass
178 regClass (VirtualRegI _) = RcInteger
179 regClass (VirtualRegHi _) = RcInteger
180 regClass (VirtualRegF u) = pprPanic ("regClass(ppc):VirtualRegF ") (ppr u)
181 regClass (VirtualRegD _) = RcDouble
184 | otherwise = RcDouble
187 showReg :: RegNo -> String
189 | n >= 0 && n <= 31 = "%r" ++ show n
190 | n >= 32 && n <= 63 = "%f" ++ show (n - 32)
191 | otherwise = "%unknown_powerpc_real_reg_" ++ show n
195 -- machine specific ------------------------------------------------------------
197 allFPArgRegs :: [Reg]
198 #if defined(darwin_TARGET_OS)
199 allFPArgRegs = map (RealReg . fReg) [1..13]
201 #elif defined(linux_TARGET_OS)
202 allFPArgRegs = map (RealReg . fReg) [1..8]
205 allFPArgRegs = panic "PPC.Regs.allFPArgRegs: not defined for this architecture"
209 fits16Bits :: Integral a => a -> Bool
210 fits16Bits x = x >= -32768 && x < 32768
212 makeImmediate :: Integral a => Width -> Bool -> a -> Maybe Imm
213 makeImmediate rep signed x = fmap ImmInt (toI16 rep signed)
215 narrow W32 False = fromIntegral (fromIntegral x :: Word32)
216 narrow W16 False = fromIntegral (fromIntegral x :: Word16)
217 narrow W8 False = fromIntegral (fromIntegral x :: Word8)
218 narrow W32 True = fromIntegral (fromIntegral x :: Int32)
219 narrow W16 True = fromIntegral (fromIntegral x :: Int16)
220 narrow W8 True = fromIntegral (fromIntegral x :: Int8)
221 narrow _ _ = panic "PPC.Regs.narrow: no match"
223 narrowed = narrow rep signed
226 | narrowed >= -32768 && narrowed < 32768 = Just narrowed
227 | otherwise = Nothing
229 | narrowed >= 0 && narrowed < 65536 = Just narrowed
230 | otherwise = Nothing
231 toI16 _ _ = Just narrowed
235 The PowerPC has 64 registers of interest; 32 integer registers and 32 floating
242 sp, r3, r4, r27, r28, f1, f20, f21 :: Reg
248 f1 = RealReg $ fReg 1
249 f20 = RealReg $ fReg 20
250 f21 = RealReg $ fReg 21
254 -- horror show -----------------------------------------------------------------
255 freeReg :: RegNo -> FastBool
256 globalRegMaybe :: GlobalReg -> Maybe Reg
259 #if powerpc_TARGET_ARCH
293 #ifdef darwin_TARGET_OS
363 freeReg 0 = fastBool False -- Hack: r0 can't be used in all insns, but it's actually free
364 freeReg 1 = fastBool False -- The Stack Pointer
365 #if !darwin_TARGET_OS
366 -- most non-darwin powerpc OSes use r2 as a TOC pointer or something like that
367 freeReg 2 = fastBool False
371 freeReg REG_Base = fastBool False
374 freeReg REG_R1 = fastBool False
377 freeReg REG_R2 = fastBool False
380 freeReg REG_R3 = fastBool False
383 freeReg REG_R4 = fastBool False
386 freeReg REG_R5 = fastBool False
389 freeReg REG_R6 = fastBool False
392 freeReg REG_R7 = fastBool False
395 freeReg REG_R8 = fastBool False
398 freeReg REG_F1 = fastBool False
401 freeReg REG_F2 = fastBool False
404 freeReg REG_F3 = fastBool False
407 freeReg REG_F4 = fastBool False
410 freeReg REG_D1 = fastBool False
413 freeReg REG_D2 = fastBool False
416 freeReg REG_Sp = fastBool False
419 freeReg REG_Su = fastBool False
422 freeReg REG_SpLim = fastBool False
425 freeReg REG_Hp = fastBool False
428 freeReg REG_HpLim = fastBool False
430 freeReg _ = fastBool True
433 -- | Returns 'Nothing' if this global register is not stored
434 -- in a real machine register, otherwise returns @'Just' reg@, where
435 -- reg is the machine register it is stored in.
439 globalRegMaybe BaseReg = Just (RealReg REG_Base)
442 globalRegMaybe (VanillaReg 1 _) = Just (RealReg REG_R1)
445 globalRegMaybe (VanillaReg 2 _) = Just (RealReg REG_R2)
448 globalRegMaybe (VanillaReg 3 _) = Just (RealReg REG_R3)
451 globalRegMaybe (VanillaReg 4 _) = Just (RealReg REG_R4)
454 globalRegMaybe (VanillaReg 5 _) = Just (RealReg REG_R5)
457 globalRegMaybe (VanillaReg 6 _) = Just (RealReg REG_R6)
460 globalRegMaybe (VanillaReg 7 _) = Just (RealReg REG_R7)
463 globalRegMaybe (VanillaReg 8 _) = Just (RealReg REG_R8)
466 globalRegMaybe (VanillaReg 9 _) = Just (RealReg REG_R9)
469 globalRegMaybe (VanillaReg 10 _) = Just (RealReg REG_R10)
472 globalRegMaybe (FloatReg 1) = Just (RealReg REG_F1)
475 globalRegMaybe (FloatReg 2) = Just (RealReg REG_F2)
478 globalRegMaybe (FloatReg 3) = Just (RealReg REG_F3)
481 globalRegMaybe (FloatReg 4) = Just (RealReg REG_F4)
484 globalRegMaybe (DoubleReg 1) = Just (RealReg REG_D1)
487 globalRegMaybe (DoubleReg 2) = Just (RealReg REG_D2)
490 globalRegMaybe Sp = Just (RealReg REG_Sp)
493 globalRegMaybe (LongReg 1) = Just (RealReg REG_Lng1)
496 globalRegMaybe (LongReg 2) = Just (RealReg REG_Lng2)
499 globalRegMaybe SpLim = Just (RealReg REG_SpLim)
502 globalRegMaybe Hp = Just (RealReg REG_Hp)
505 globalRegMaybe HpLim = Just (RealReg REG_HpLim)
507 #ifdef REG_CurrentTSO
508 globalRegMaybe CurrentTSO = Just (RealReg REG_CurrentTSO)
510 #ifdef REG_CurrentNursery
511 globalRegMaybe CurrentNursery = Just (RealReg REG_CurrentNursery)
513 globalRegMaybe _ = Nothing
516 #else /* powerpc_TARGET_ARCH */
519 globalRegMaybe _ = panic "PPC.Regs.globalRegMaybe: not defined"
521 #endif /* powerpc_TARGET_ARCH */
524 -- We map STG registers onto appropriate CmmExprs. Either they map
525 -- to real machine registers or stored as offsets from BaseReg. Given
526 -- a GlobalReg, get_GlobalReg_reg_or_addr produces either the real
527 -- register it is in, on this platform, or a CmmExpr denoting the
528 -- address in the register table holding it.
529 -- (See also get_GlobalReg_addr in CgUtils.)
531 get_GlobalReg_reg_or_addr :: GlobalReg -> Either Reg CmmExpr
532 get_GlobalReg_reg_or_addr mid
533 = case globalRegMaybe mid of
535 Nothing -> Right (get_GlobalReg_addr mid)
538 -- allocatableRegs is allMachRegNos with the fixed-use regs removed.
539 -- i.e., these are the regs for which we are prepared to allow the
540 -- register allocator to attempt to map VRegs to.
541 allocatableRegs :: [RegNo]
543 = let isFree i = isFastTrue (freeReg i)
544 in filter isFree allMachRegNos