80c68dd0969486f38233b36aa8fa7348db961eff
[ghc-hetmet.git] / compiler / nativeGen / PPC / Regs.hs
1 -- -----------------------------------------------------------------------------
2 --
3 -- (c) The University of Glasgow 1994-2004
4 -- 
5 -- -----------------------------------------------------------------------------
6
7 module PPC.Regs (
8         -- immediates
9         Imm(..),
10         strImmLit,
11         litToImm,
12
13         -- addressing modes
14         AddrMode(..),
15         addrOffset,
16
17         -- registers
18         spRel,
19         argRegs,
20         allArgRegs,
21         callClobberedRegs,
22         allMachRegNos,
23         regClass,
24         showReg,
25         
26         -- machine specific
27         allFPArgRegs,
28         fits16Bits,
29         makeImmediate,
30         fReg,
31         sp, r3, r4, r27, r28, f1, f20, f21,
32
33         -- horrow show
34         freeReg,
35         globalRegMaybe,
36         get_GlobalReg_reg_or_addr,
37         allocatableRegs
38
39 )
40
41 where
42
43 #include "nativeGen/NCG.h"
44 #include "HsVersions.h"
45 #include "../includes/MachRegs.h"
46
47 import Reg
48 import RegClass
49
50 import CgUtils          ( get_GlobalReg_addr )
51 import BlockId
52 import Cmm
53 import CLabel           ( CLabel )
54 import Pretty
55 import Outputable       ( Outputable(..), pprPanic, panic )
56 import qualified Outputable
57 import Constants
58 import FastBool
59
60 import Data.Word        ( Word8, Word16, Word32 )
61 import Data.Int         ( Int8, Int16, Int32 )
62
63
64 -- immediates ------------------------------------------------------------------
65 data Imm
66         = ImmInt        Int
67         | ImmInteger    Integer     -- Sigh.
68         | ImmCLbl       CLabel      -- AbstractC Label (with baggage)
69         | ImmLit        Doc         -- Simple string
70         | ImmIndex    CLabel Int
71         | ImmFloat      Rational
72         | ImmDouble     Rational
73         | ImmConstantSum Imm Imm
74         | ImmConstantDiff Imm Imm
75         | LO Imm
76         | HI Imm
77         | HA Imm        {- high halfword adjusted -}
78
79
80 strImmLit :: String -> Imm
81 strImmLit s = ImmLit (text s)
82
83
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)
94                              = ImmConstantSum
95                                (ImmConstantDiff (ImmCLbl l1) (ImmCLbl l2))
96                                (ImmInt off)
97 litToImm (CmmBlock id)       = ImmCLbl (infoTblLbl id)
98 litToImm _                   = panic "PPC.Regs.litToImm: no match"
99
100
101 -- addressing modes ------------------------------------------------------------
102
103 data AddrMode
104         = AddrRegReg    Reg Reg
105         | AddrRegImm    Reg Imm
106
107
108 addrOffset :: AddrMode -> Int -> Maybe AddrMode
109 addrOffset addr off
110   = case addr of
111       AddrRegImm r (ImmInt n)
112        | fits16Bits n2 -> Just (AddrRegImm r (ImmInt n2))
113        | otherwise     -> Nothing
114        where n2 = n + off
115
116       AddrRegImm r (ImmInteger n)
117        | fits16Bits n2 -> Just (AddrRegImm r (ImmInt (fromInteger n2)))
118        | otherwise     -> Nothing
119        where n2 = n + toInteger off
120        
121       _ -> Nothing
122
123
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.
128
129 spRel :: Int    -- desired stack offset in words, positive or negative
130       -> AddrMode
131
132 spRel n = AddrRegImm sp (ImmInt (n * wORD_SIZE))
133
134
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]
140 argRegs 0 = []
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!"
150
151
152 allArgRegs :: [Reg]
153 allArgRegs = map RealReg [3..10]
154
155
156 -- these are the regs which we cannot assume stay alive over a C call.  
157 callClobberedRegs :: [Reg]
158 #if   defined(darwin_TARGET_OS)
159 callClobberedRegs
160   = map RealReg (0:[2..12] ++ map fReg [0..13])
161
162 #elif defined(linux_TARGET_OS)
163 callClobberedRegs
164   = map RealReg (0:[2..13] ++ map fReg [0..13])
165
166 #else
167 callClobberedRegs
168         = panic "PPC.Regs.callClobberedRegs: not defined for this architecture"
169 #endif
170
171
172 allMachRegNos   :: [RegNo]
173 allMachRegNos   = [0..63]
174
175
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
182 regClass (RealReg i) 
183         | i < 32        = RcInteger 
184         | otherwise     = RcDouble
185
186
187 showReg :: RegNo -> String
188 showReg n
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
192
193
194
195 -- machine specific ------------------------------------------------------------
196
197 allFPArgRegs :: [Reg]
198 #if    defined(darwin_TARGET_OS)
199 allFPArgRegs = map (RealReg . fReg) [1..13]
200
201 #elif  defined(linux_TARGET_OS)
202 allFPArgRegs = map (RealReg . fReg) [1..8]
203
204 #else
205 allFPArgRegs = panic "PPC.Regs.allFPArgRegs: not defined for this architecture"
206
207 #endif
208
209 fits16Bits :: Integral a => a -> Bool
210 fits16Bits x = x >= -32768 && x < 32768
211
212 makeImmediate :: Integral a => Width -> Bool -> a -> Maybe Imm
213 makeImmediate rep signed x = fmap ImmInt (toI16 rep signed)
214     where
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"
222         
223         narrowed = narrow rep signed
224         
225         toI16 W32 True
226             | narrowed >= -32768 && narrowed < 32768 = Just narrowed
227             | otherwise = Nothing
228         toI16 W32 False
229             | narrowed >= 0 && narrowed < 65536 = Just narrowed
230             | otherwise = Nothing
231         toI16 _ _  = Just narrowed
232
233
234 {-
235 The PowerPC has 64 registers of interest; 32 integer registers and 32 floating
236 point registers.
237 -}
238
239 fReg :: Int -> RegNo
240 fReg x = (32 + x)
241
242 sp, r3, r4, r27, r28, f1, f20, f21 :: Reg
243 sp      = RealReg 1
244 r3      = RealReg 3
245 r4      = RealReg 4
246 r27     = RealReg 27
247 r28     = RealReg 28
248 f1      = RealReg $ fReg 1
249 f20     = RealReg $ fReg 20
250 f21     = RealReg $ fReg 21
251
252
253
254 -- horror show -----------------------------------------------------------------
255 freeReg :: RegNo -> FastBool
256 globalRegMaybe :: GlobalReg -> Maybe Reg
257
258
259 #if powerpc_TARGET_ARCH
260 #define r0 0
261 #define r1 1
262 #define r2 2
263 #define r3 3
264 #define r4 4
265 #define r5 5
266 #define r6 6
267 #define r7 7
268 #define r8 8
269 #define r9 9
270 #define r10 10
271 #define r11 11
272 #define r12 12
273 #define r13 13
274 #define r14 14
275 #define r15 15
276 #define r16 16
277 #define r17 17
278 #define r18 18
279 #define r19 19
280 #define r20 20
281 #define r21 21
282 #define r22 22
283 #define r23 23
284 #define r24 24
285 #define r25 25
286 #define r26 26
287 #define r27 27
288 #define r28 28
289 #define r29 29
290 #define r30 30
291 #define r31 31
292
293 #ifdef darwin_TARGET_OS
294 #define f0  32
295 #define f1  33
296 #define f2  34
297 #define f3  35
298 #define f4  36
299 #define f5  37
300 #define f6  38
301 #define f7  39
302 #define f8  40
303 #define f9  41
304 #define f10 42
305 #define f11 43
306 #define f12 44
307 #define f13 45
308 #define f14 46
309 #define f15 47
310 #define f16 48
311 #define f17 49
312 #define f18 50
313 #define f19 51
314 #define f20 52
315 #define f21 53
316 #define f22 54
317 #define f23 55
318 #define f24 56
319 #define f25 57
320 #define f26 58
321 #define f27 59
322 #define f28 60
323 #define f29 61
324 #define f30 62
325 #define f31 63
326 #else
327 #define fr0  32
328 #define fr1  33
329 #define fr2  34
330 #define fr3  35
331 #define fr4  36
332 #define fr5  37
333 #define fr6  38
334 #define fr7  39
335 #define fr8  40
336 #define fr9  41
337 #define fr10 42
338 #define fr11 43
339 #define fr12 44
340 #define fr13 45
341 #define fr14 46
342 #define fr15 47
343 #define fr16 48
344 #define fr17 49
345 #define fr18 50
346 #define fr19 51
347 #define fr20 52
348 #define fr21 53
349 #define fr22 54
350 #define fr23 55
351 #define fr24 56
352 #define fr25 57
353 #define fr26 58
354 #define fr27 59
355 #define fr28 60
356 #define fr29 61
357 #define fr30 62
358 #define fr31 63
359 #endif
360
361
362
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
368 #endif
369
370 #ifdef REG_Base
371 freeReg REG_Base = fastBool False
372 #endif
373 #ifdef REG_R1
374 freeReg REG_R1   = fastBool False
375 #endif  
376 #ifdef REG_R2  
377 freeReg REG_R2   = fastBool False
378 #endif  
379 #ifdef REG_R3  
380 freeReg REG_R3   = fastBool False
381 #endif  
382 #ifdef REG_R4  
383 freeReg REG_R4   = fastBool False
384 #endif  
385 #ifdef REG_R5  
386 freeReg REG_R5   = fastBool False
387 #endif  
388 #ifdef REG_R6  
389 freeReg REG_R6   = fastBool False
390 #endif  
391 #ifdef REG_R7  
392 freeReg REG_R7   = fastBool False
393 #endif  
394 #ifdef REG_R8  
395 freeReg REG_R8   = fastBool False
396 #endif
397 #ifdef REG_F1
398 freeReg REG_F1 = fastBool False
399 #endif
400 #ifdef REG_F2
401 freeReg REG_F2 = fastBool False
402 #endif
403 #ifdef REG_F3
404 freeReg REG_F3 = fastBool False
405 #endif
406 #ifdef REG_F4
407 freeReg REG_F4 = fastBool False
408 #endif
409 #ifdef REG_D1
410 freeReg REG_D1 = fastBool False
411 #endif
412 #ifdef REG_D2
413 freeReg REG_D2 = fastBool False
414 #endif
415 #ifdef REG_Sp 
416 freeReg REG_Sp   = fastBool False
417 #endif 
418 #ifdef REG_Su
419 freeReg REG_Su   = fastBool False
420 #endif 
421 #ifdef REG_SpLim 
422 freeReg REG_SpLim = fastBool False
423 #endif 
424 #ifdef REG_Hp 
425 freeReg REG_Hp   = fastBool False
426 #endif
427 #ifdef REG_HpLim
428 freeReg REG_HpLim = fastBool False
429 #endif
430 freeReg _               = fastBool True
431
432
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.
436
437
438 #ifdef REG_Base
439 globalRegMaybe BaseReg                  = Just (RealReg REG_Base)
440 #endif
441 #ifdef REG_R1
442 globalRegMaybe (VanillaReg 1 _)         = Just (RealReg REG_R1)
443 #endif 
444 #ifdef REG_R2 
445 globalRegMaybe (VanillaReg 2 _)         = Just (RealReg REG_R2)
446 #endif 
447 #ifdef REG_R3 
448 globalRegMaybe (VanillaReg 3 _)         = Just (RealReg REG_R3)
449 #endif 
450 #ifdef REG_R4 
451 globalRegMaybe (VanillaReg 4 _)         = Just (RealReg REG_R4)
452 #endif 
453 #ifdef REG_R5 
454 globalRegMaybe (VanillaReg 5 _)         = Just (RealReg REG_R5)
455 #endif 
456 #ifdef REG_R6 
457 globalRegMaybe (VanillaReg 6 _)         = Just (RealReg REG_R6)
458 #endif 
459 #ifdef REG_R7 
460 globalRegMaybe (VanillaReg 7 _)         = Just (RealReg REG_R7)
461 #endif 
462 #ifdef REG_R8 
463 globalRegMaybe (VanillaReg 8 _)         = Just (RealReg REG_R8)
464 #endif
465 #ifdef REG_R9 
466 globalRegMaybe (VanillaReg 9 _)         = Just (RealReg REG_R9)
467 #endif
468 #ifdef REG_R10 
469 globalRegMaybe (VanillaReg 10 _)        = Just (RealReg REG_R10)
470 #endif
471 #ifdef REG_F1
472 globalRegMaybe (FloatReg 1)             = Just (RealReg REG_F1)
473 #endif                                  
474 #ifdef REG_F2                           
475 globalRegMaybe (FloatReg 2)             = Just (RealReg REG_F2)
476 #endif                                  
477 #ifdef REG_F3                           
478 globalRegMaybe (FloatReg 3)             = Just (RealReg REG_F3)
479 #endif                                  
480 #ifdef REG_F4                           
481 globalRegMaybe (FloatReg 4)             = Just (RealReg REG_F4)
482 #endif                                  
483 #ifdef REG_D1                           
484 globalRegMaybe (DoubleReg 1)            = Just (RealReg REG_D1)
485 #endif                                  
486 #ifdef REG_D2                           
487 globalRegMaybe (DoubleReg 2)            = Just (RealReg REG_D2)
488 #endif
489 #ifdef REG_Sp       
490 globalRegMaybe Sp                       = Just (RealReg REG_Sp)
491 #endif
492 #ifdef REG_Lng1                         
493 globalRegMaybe (LongReg 1)              = Just (RealReg REG_Lng1)
494 #endif                                  
495 #ifdef REG_Lng2                         
496 globalRegMaybe (LongReg 2)              = Just (RealReg REG_Lng2)
497 #endif
498 #ifdef REG_SpLim                                
499 globalRegMaybe SpLim                    = Just (RealReg REG_SpLim)
500 #endif                                  
501 #ifdef REG_Hp                           
502 globalRegMaybe Hp                       = Just (RealReg REG_Hp)
503 #endif                                  
504 #ifdef REG_HpLim                        
505 globalRegMaybe HpLim                    = Just (RealReg REG_HpLim)
506 #endif                                  
507 #ifdef REG_CurrentTSO                           
508 globalRegMaybe CurrentTSO               = Just (RealReg REG_CurrentTSO)
509 #endif                                  
510 #ifdef REG_CurrentNursery                       
511 globalRegMaybe CurrentNursery           = Just (RealReg REG_CurrentNursery)
512 #endif                                  
513 globalRegMaybe _                        = Nothing
514
515
516 #else  /* powerpc_TARGET_ARCH */
517
518 freeReg _               = 0#
519 globalRegMaybe _        = panic "PPC.Regs.globalRegMaybe: not defined"
520
521 #endif /* powerpc_TARGET_ARCH */
522
523
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.)
530
531 get_GlobalReg_reg_or_addr :: GlobalReg -> Either Reg CmmExpr
532 get_GlobalReg_reg_or_addr mid
533    = case globalRegMaybe mid of
534         Just rr -> Left rr
535         Nothing -> Right (get_GlobalReg_addr mid)
536
537
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]
542 allocatableRegs
543    = let isFree i = isFastTrue (freeReg i)
544      in  filter isFree allMachRegNos