NCG: Split MachRegs.hs into arch specific modules
[ghc-hetmet.git] / compiler / nativeGen / SPARC / Regs.hs
1 -- -----------------------------------------------------------------------------
2 --
3 -- (c) The University of Glasgow 1994-2004
4 -- 
5 -- -----------------------------------------------------------------------------
6
7 module SPARC.Regs (
8
9         -- sizes
10         Size(..),
11         intSize, 
12         floatSize, 
13         isFloatSize, 
14         wordSize,
15         cmmTypeSize,
16         sizeToWidth,
17         mkVReg,
18
19         -- immediate values
20         Imm(..),
21         strImmLit,
22         litToImm,
23
24         -- addressing modes
25         AddrMode(..),
26         addrOffset,
27
28         -- registers
29         spRel,
30         argRegs, 
31         allArgRegs, 
32         callClobberedRegs,
33         allMachRegNos,
34         regClass,
35         showReg,
36
37         -- machine specific info
38         fpRel,
39         fits13Bits, 
40         largeOffsetError,
41         gReg, iReg, lReg, oReg, fReg,
42         fp, sp, g0, g1, g2, o0, o1, f0, f6, f8, f26, f27,
43         nCG_FirstFloatReg,
44
45         -- horror show
46         freeReg,
47         globalRegMaybe
48 )
49
50 where
51
52 #include "nativeGen/NCG.h"
53 #include "HsVersions.h"
54 #include "../includes/MachRegs.h"
55
56 import RegsBase
57
58 import BlockId
59 import Cmm
60 import CLabel           ( CLabel )
61 import Pretty
62 import Outputable       ( Outputable(..), pprPanic, panic )
63 import qualified Outputable
64 import Unique
65 import Constants
66 import FastBool
67
68
69 data Size
70         = II8     -- byte (signed)
71 --      | II8u    -- byte (unsigned)
72         | II16    -- halfword (signed, 2 bytes)
73 --      | II16u   -- halfword (unsigned, 2 bytes)
74         | II32    -- word (4 bytes)
75         | II64    -- word (8 bytes)
76         | FF32    -- IEEE single-precision floating pt
77         | FF64    -- IEEE single-precision floating pt
78         deriving Eq
79
80
81 intSize, floatSize :: Width -> Size
82 intSize W8      = II8
83 --intSize W16 = II16u
84 intSize W16     = II16
85 intSize W32     = II32
86 intSize W64     = II64
87 intSize other   = pprPanic "MachInstrs.intSize" (ppr other)
88
89 floatSize W32   = FF32
90 floatSize W64   = FF64
91 floatSize other = pprPanic "MachInstrs.intSize" (ppr other)
92
93
94 isFloatSize :: Size -> Bool
95 isFloatSize FF32        = True
96 isFloatSize FF64        = True
97 isFloatSize _           = False
98
99
100 wordSize :: Size
101 wordSize = intSize wordWidth
102
103
104 cmmTypeSize :: CmmType -> Size
105 cmmTypeSize ty 
106         | isFloatType ty        = floatSize (typeWidth ty)
107         | otherwise             = intSize (typeWidth ty)
108
109
110 sizeToWidth :: Size -> Width
111 sizeToWidth size
112  = case size of
113         II8             -> W8
114 --      II8u            -> W8
115         II16            -> W16
116 --      II16u           -> W16
117         II32            -> W32
118         II64            -> W64
119         FF32            -> W32
120         FF64            -> W64
121
122
123 mkVReg :: Unique -> Size -> Reg
124 mkVReg u size
125         | not (isFloatSize size) 
126         = VirtualRegI u
127
128         | otherwise
129         = case size of
130                 FF32    -> VirtualRegF u
131                 FF64    -> VirtualRegD u
132                 _       -> panic "mkVReg"
133
134
135 -- immediates ------------------------------------------------------------------
136 data Imm
137         = ImmInt        Int
138         | ImmInteger    Integer     -- Sigh.
139         | ImmCLbl       CLabel      -- AbstractC Label (with baggage)
140         | ImmLit        Doc         -- Simple string
141         | ImmIndex    CLabel Int
142         | ImmFloat      Rational
143         | ImmDouble     Rational
144         | ImmConstantSum Imm Imm
145         | ImmConstantDiff Imm Imm
146         | LO Imm                    {- Possible restrictions... -}
147         | HI Imm
148
149
150 strImmLit :: String -> Imm
151 strImmLit s = ImmLit (text s)
152
153
154 -- narrow to the width: a CmmInt might be out of
155 -- range, but we assume that ImmInteger only contains
156 -- in-range values.  A signed value should be fine here.
157 litToImm :: CmmLit -> Imm
158 litToImm (CmmInt i w)        = ImmInteger (narrowS w i)
159 litToImm (CmmFloat f W32)    = ImmFloat f
160 litToImm (CmmFloat f W64)    = ImmDouble f
161 litToImm (CmmLabel l)        = ImmCLbl l
162 litToImm (CmmLabelOff l off) = ImmIndex l off
163
164 litToImm (CmmLabelDiffOff l1 l2 off)
165                              = ImmConstantSum
166                                (ImmConstantDiff (ImmCLbl l1) (ImmCLbl l2))
167                                (ImmInt off)
168 litToImm (CmmBlock id)          = ImmCLbl (infoTblLbl id)
169 litToImm _
170         = panic "SPARC.Regs.litToImm: no match"
171
172 -- addressing modes ------------------------------------------------------------
173 data AddrMode
174         = AddrRegReg    Reg Reg
175         | AddrRegImm    Reg Imm
176
177
178 addrOffset :: AddrMode -> Int -> Maybe AddrMode
179 addrOffset addr off
180   = case addr of
181       AddrRegImm r (ImmInt n)
182        | fits13Bits n2 -> Just (AddrRegImm r (ImmInt n2))
183        | otherwise     -> Nothing
184        where n2 = n + off
185
186       AddrRegImm r (ImmInteger n)
187        | fits13Bits n2 -> Just (AddrRegImm r (ImmInt (fromInteger n2)))
188        | otherwise     -> Nothing
189        where n2 = n + toInteger off
190
191       AddrRegReg r (RealReg 0)
192        | fits13Bits off -> Just (AddrRegImm r (ImmInt off))
193        | otherwise     -> Nothing
194        
195       _ -> Nothing
196
197
198
199 -- registers -------------------------------------------------------------------
200
201 -- @spRel@ gives us a stack relative addressing mode for volatile
202 -- temporaries and for excess call arguments.  @fpRel@, where
203 -- applicable, is the same but for the frame pointer.
204 spRel :: Int    -- desired stack offset in words, positive or negative
205       -> AddrMode
206
207 spRel n = AddrRegImm sp (ImmInt (n * wORD_SIZE))
208
209
210 argRegs :: RegNo -> [Reg]
211 argRegs 0 = []
212 argRegs 1 = map (RealReg . oReg) [0]
213 argRegs 2 = map (RealReg . oReg) [0,1]
214 argRegs 3 = map (RealReg . oReg) [0,1,2]
215 argRegs 4 = map (RealReg . oReg) [0,1,2,3]
216 argRegs 5 = map (RealReg . oReg) [0,1,2,3,4]
217 argRegs 6 = map (RealReg . oReg) [0,1,2,3,4,5]
218 argRegs _ = panic "MachRegs.argRegs(sparc): don't know about >6 arguments!"
219
220
221 allArgRegs :: [Reg]
222 allArgRegs = map RealReg [oReg i | i <- [0..5]]
223
224
225 -- These are the regs which we cannot assume stay alive over a C call.  
226 callClobberedRegs :: [Reg]
227 callClobberedRegs
228         = map RealReg 
229                 ( oReg 7 :
230                   [oReg i | i <- [0..5]] ++
231                   [gReg i | i <- [1..7]] ++
232                   [fReg i | i <- [0..31]] )
233
234
235 allMachRegNos :: [RegNo]
236 allMachRegNos
237         = ([0..31]
238                ++ [32,34 .. nCG_FirstFloatReg-1]
239                ++ [nCG_FirstFloatReg .. 63])    
240
241
242 -- | Get the class of a register.
243 {-# INLINE regClass      #-}
244 regClass :: Reg -> RegClass
245 regClass (VirtualRegI  _)       = RcInteger
246 regClass (VirtualRegHi _)       = RcInteger
247 regClass (VirtualRegF  _)       = RcFloat
248 regClass (VirtualRegD  _)       = RcDouble
249 regClass (RealReg i) 
250         | i < 32                = RcInteger 
251         | i < nCG_FirstFloatReg = RcDouble
252         | otherwise             = RcFloat
253
254
255 showReg :: RegNo -> String
256 showReg n
257    | n >= 0  && n < 8   = "%g" ++ show n
258    | n >= 8  && n < 16  = "%o" ++ show (n-8)
259    | n >= 16 && n < 24  = "%l" ++ show (n-16)
260    | n >= 24 && n < 32  = "%i" ++ show (n-24)
261    | n >= 32 && n < 64  = "%f" ++ show (n-32)
262    | otherwise          = "%unknown_sparc_real_reg_" ++ show n
263
264
265 -- machine specific ------------------------------------------------------------
266
267 -- Duznae work for offsets greater than 13 bits; we just hope for the best
268 fpRel :: Int -> AddrMode
269 fpRel n
270   = AddrRegImm fp (ImmInt (n * wORD_SIZE))
271
272
273 {-# SPECIALIZE fits13Bits :: Int -> Bool, Integer -> Bool #-}
274 fits13Bits :: Integral a => a -> Bool
275 fits13Bits x = x >= -4096 && x < 4096
276
277
278 largeOffsetError :: Integral a => a -> b
279 largeOffsetError i
280   = error ("ERROR: SPARC native-code generator cannot handle large offset ("
281            ++ show i ++ ");\nprobably because of large constant data structures;" ++ 
282            "\nworkaround: use -fvia-C on this module.\n")
283
284
285 {-
286 The SPARC has 64 registers of interest; 32 integer registers and 32
287 floating point registers.  The mapping of STG registers to SPARC
288 machine registers is defined in StgRegs.h.  We are, of course,
289 prepared for any eventuality.
290
291 The whole fp-register pairing thing on sparcs is a huge nuisance.  See
292 fptools/ghc/includes/MachRegs.h for a description of what's going on
293 here.
294 -}
295
296
297 gReg,lReg,iReg,oReg,fReg :: Int -> RegNo
298 gReg x = x
299 oReg x = (8 + x)
300 lReg x = (16 + x)
301 iReg x = (24 + x)
302 fReg x = (32 + x)
303
304
305 g0, g1, g2, fp, sp, o0, o1, f0, f6, f8, f22, f26, f27 :: Reg
306 f6  = RealReg (fReg 6)
307 f8  = RealReg (fReg 8)
308 f22 = RealReg (fReg 22)
309 f26 = RealReg (fReg 26)
310 f27 = RealReg (fReg 27)
311
312
313 -- g0 is useful for codegen; is always zero, and writes to it vanish.
314 g0  = RealReg (gReg 0)
315 g1  = RealReg (gReg 1)
316 g2  = RealReg (gReg 2)
317
318
319 -- FP, SP, int and float return (from C) regs.
320 fp  = RealReg (iReg 6)
321 sp  = RealReg (oReg 6)
322 o0  = RealReg (oReg 0)
323 o1  = RealReg (oReg 1)
324 f0  = RealReg (fReg 0)
325
326
327 nCG_FirstFloatReg :: RegNo
328 nCG_FirstFloatReg = unRealReg NCG_FirstFloatReg
329
330
331 -- horror show -----------------------------------------------------------------
332 #if sparc_TARGET_ARCH
333 #define g0 0
334 #define g1 1
335 #define g2 2
336 #define g3 3
337 #define g4 4
338 #define g5 5
339 #define g6 6
340 #define g7 7
341 #define o0 8
342 #define o1 9
343 #define o2 10
344 #define o3 11
345 #define o4 12
346 #define o5 13
347 #define o6 14
348 #define o7 15
349 #define l0 16
350 #define l1 17
351 #define l2 18
352 #define l3 19
353 #define l4 20
354 #define l5 21
355 #define l6 22
356 #define l7 23
357 #define i0 24
358 #define i1 25
359 #define i2 26
360 #define i3 27
361 #define i4 28
362 #define i5 29
363 #define i6 30
364 #define i7 31
365
366 #define f0  32
367 #define f1  33
368 #define f2  34
369 #define f3  35
370 #define f4  36
371 #define f5  37
372 #define f6  38
373 #define f7  39
374 #define f8  40
375 #define f9  41
376 #define f10 42
377 #define f11 43
378 #define f12 44
379 #define f13 45
380 #define f14 46
381 #define f15 47
382 #define f16 48
383 #define f17 49
384 #define f18 50
385 #define f19 51
386 #define f20 52
387 #define f21 53
388 #define f22 54
389 #define f23 55
390 #define f24 56
391 #define f25 57
392 #define f26 58
393 #define f27 59
394 #define f28 60
395 #define f29 61
396 #define f30 62
397 #define f31 63
398 #endif
399
400
401 freeReg :: RegNo -> FastBool
402
403 freeReg g0 = fastBool False  -- %g0 is always 0.
404
405 freeReg g5 = fastBool False  -- %g5 is reserved (ABI).
406 freeReg g6 = fastBool False  -- %g6 is reserved (ABI).
407 freeReg g7 = fastBool False  -- %g7 is reserved (ABI).
408 freeReg i6 = fastBool False  -- %i6 is our frame pointer.
409 freeReg i7 = fastBool False  -- %i7 tends to have ret-addr-ish things
410 freeReg o6 = fastBool False  -- %o6 is our stack pointer.
411 freeReg o7 = fastBool False  -- %o7 holds ret addrs (???)
412 freeReg f0 = fastBool False  --  %f0/%f1 are the C fp return registers.
413 freeReg f1 = fastBool False
414
415 -- TODO: Not sure about these BL 2009/01/10
416 --      Used for NCG spill tmps? what is this?
417
418 {-
419 freeReg g1  = fastBool False  -- %g1 is used for NCG spill tmp
420 freeReg g2  = fastBool False 
421 freeReg f6  = fastBool False
422 freeReg f8  = fastBool False
423 freeReg f26 = fastBool False
424 freeReg f27 = fastBool False
425 -}
426
427 #ifdef REG_Base
428 freeReg REG_Base = fastBool False
429 #endif
430 #ifdef REG_R1
431 freeReg REG_R1   = fastBool False
432 #endif  
433 #ifdef REG_R2  
434 freeReg REG_R2   = fastBool False
435 #endif  
436 #ifdef REG_R3  
437 freeReg REG_R3   = fastBool False
438 #endif  
439 #ifdef REG_R4  
440 freeReg REG_R4   = fastBool False
441 #endif  
442 #ifdef REG_R5  
443 freeReg REG_R5   = fastBool False
444 #endif  
445 #ifdef REG_R6  
446 freeReg REG_R6   = fastBool False
447 #endif  
448 #ifdef REG_R7  
449 freeReg REG_R7   = fastBool False
450 #endif  
451 #ifdef REG_R8  
452 freeReg REG_R8   = fastBool False
453 #endif
454 #ifdef REG_F1
455 freeReg REG_F1 = fastBool False
456 #endif
457 #ifdef REG_F2
458 freeReg REG_F2 = fastBool False
459 #endif
460 #ifdef REG_F3
461 freeReg REG_F3 = fastBool False
462 #endif
463 #ifdef REG_F4
464 freeReg REG_F4 = fastBool False
465 #endif
466 #ifdef REG_D1
467 freeReg REG_D1 = fastBool False
468 #endif
469 #ifdef REG_D2
470 freeReg REG_D2 = fastBool False
471 #endif
472 #ifdef REG_Sp 
473 freeReg REG_Sp   = fastBool False
474 #endif 
475 #ifdef REG_Su
476 freeReg REG_Su   = fastBool False
477 #endif 
478 #ifdef REG_SpLim 
479 freeReg REG_SpLim = fastBool False
480 #endif 
481 #ifdef REG_Hp 
482 freeReg REG_Hp   = fastBool False
483 #endif
484 #ifdef REG_HpLim
485 freeReg REG_HpLim = fastBool False
486 #endif
487 freeReg _         = fastBool True
488
489
490
491 --  | Returns 'Nothing' if this global register is not stored
492 -- in a real machine register, otherwise returns @'Just' reg@, where
493 -- reg is the machine register it is stored in.
494
495 globalRegMaybe :: GlobalReg -> Maybe Reg
496
497 #ifdef REG_Base
498 globalRegMaybe BaseReg                  = Just (RealReg REG_Base)
499 #endif
500 #ifdef REG_R1
501 globalRegMaybe (VanillaReg 1 _)         = Just (RealReg REG_R1)
502 #endif 
503 #ifdef REG_R2 
504 globalRegMaybe (VanillaReg 2 _)         = Just (RealReg REG_R2)
505 #endif 
506 #ifdef REG_R3 
507 globalRegMaybe (VanillaReg 3 _)         = Just (RealReg REG_R3)
508 #endif 
509 #ifdef REG_R4 
510 globalRegMaybe (VanillaReg 4 _)         = Just (RealReg REG_R4)
511 #endif 
512 #ifdef REG_R5 
513 globalRegMaybe (VanillaReg 5 _)         = Just (RealReg REG_R5)
514 #endif 
515 #ifdef REG_R6 
516 globalRegMaybe (VanillaReg 6 _)         = Just (RealReg REG_R6)
517 #endif 
518 #ifdef REG_R7 
519 globalRegMaybe (VanillaReg 7 _)         = Just (RealReg REG_R7)
520 #endif 
521 #ifdef REG_R8 
522 globalRegMaybe (VanillaReg 8 _)         = Just (RealReg REG_R8)
523 #endif
524 #ifdef REG_R9 
525 globalRegMaybe (VanillaReg 9 _)         = Just (RealReg REG_R9)
526 #endif
527 #ifdef REG_R10 
528 globalRegMaybe (VanillaReg 10 _)        = Just (RealReg REG_R10)
529 #endif
530 #ifdef REG_F1
531 globalRegMaybe (FloatReg 1)             = Just (RealReg REG_F1)
532 #endif                                  
533 #ifdef REG_F2                           
534 globalRegMaybe (FloatReg 2)             = Just (RealReg REG_F2)
535 #endif                                  
536 #ifdef REG_F3                           
537 globalRegMaybe (FloatReg 3)             = Just (RealReg REG_F3)
538 #endif                                  
539 #ifdef REG_F4                           
540 globalRegMaybe (FloatReg 4)             = Just (RealReg REG_F4)
541 #endif                                  
542 #ifdef REG_D1                           
543 globalRegMaybe (DoubleReg 1)            = Just (RealReg REG_D1)
544 #endif                                  
545 #ifdef REG_D2                           
546 globalRegMaybe (DoubleReg 2)            = Just (RealReg REG_D2)
547 #endif
548 #ifdef REG_Sp       
549 globalRegMaybe Sp                       = Just (RealReg REG_Sp)
550 #endif
551 #ifdef REG_Lng1                         
552 globalRegMaybe (LongReg 1)              = Just (RealReg REG_Lng1)
553 #endif                                  
554 #ifdef REG_Lng2                         
555 globalRegMaybe (LongReg 2)              = Just (RealReg REG_Lng2)
556 #endif
557 #ifdef REG_SpLim                                
558 globalRegMaybe SpLim                    = Just (RealReg REG_SpLim)
559 #endif                                  
560 #ifdef REG_Hp                           
561 globalRegMaybe Hp                       = Just (RealReg REG_Hp)
562 #endif                                  
563 #ifdef REG_HpLim                        
564 globalRegMaybe HpLim                    = Just (RealReg REG_HpLim)
565 #endif                                  
566 #ifdef REG_CurrentTSO                           
567 globalRegMaybe CurrentTSO               = Just (RealReg REG_CurrentTSO)
568 #endif                                  
569 #ifdef REG_CurrentNursery                       
570 globalRegMaybe CurrentNursery           = Just (RealReg REG_CurrentNursery)
571 #endif                                  
572 globalRegMaybe _                        = Nothing