NCG: Validate fixes for powerpc
[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         -- sizes
9         Size(..),
10         intSize, 
11         floatSize, 
12         isFloatSize, 
13         wordSize,
14         cmmTypeSize,
15         sizeToWidth,
16         mkVReg,
17
18         -- immediates
19         Imm(..),
20         strImmLit,
21         litToImm,
22
23         -- addressing modes
24         AddrMode(..),
25         addrOffset,
26
27         -- registers
28         spRel,
29         argRegs,
30         allArgRegs,
31         callClobberedRegs,
32         allMachRegNos,
33         regClass,
34         showReg,
35         
36         -- machine specific
37         allFPArgRegs,
38         fits16Bits,
39         makeImmediate,
40         fReg,
41         sp, r3, r4, r27, r28, f1, f20, f21,
42
43         -- horrow show
44         freeReg,
45         globalRegMaybe
46 )
47
48 where
49
50 #include "nativeGen/NCG.h"
51 #include "HsVersions.h"
52 #include "../includes/MachRegs.h"
53
54 import RegsBase
55
56 import BlockId
57 import Cmm
58 import CLabel           ( CLabel )
59 import Pretty
60 import Outputable       ( Outputable(..), pprPanic, panic )
61 import qualified Outputable
62 import Unique
63 import Constants
64 import FastBool
65
66 import Data.Word        ( Word8, Word16, Word32 )
67 import Data.Int         ( Int8, Int16, Int32 )
68
69 -- sizes -----------------------------------------------------------------------
70 -- For these three, the "size" also gives the int/float
71 -- distinction, because the instructions for int/float
72 -- differ only in their suffices
73 data Size       
74         = II8 | II16 | II32 | II64 | FF32 | FF64 | FF80
75         deriving Eq
76
77 intSize, floatSize :: Width -> Size
78 intSize W8 = II8
79 intSize W16 = II16
80 intSize W32 = II32
81 intSize W64 = II64
82 intSize other = pprPanic "MachInstrs.intSize" (ppr other)
83
84 floatSize W32 = FF32
85 floatSize W64 = FF64
86 floatSize other = pprPanic "MachInstrs.intSize" (ppr other)
87
88
89 isFloatSize :: Size -> Bool
90 isFloatSize FF32 = True
91 isFloatSize FF64 = True
92 isFloatSize FF80 = True
93 isFloatSize _    = False
94
95
96 wordSize :: Size
97 wordSize = intSize wordWidth
98
99
100 cmmTypeSize :: CmmType -> Size
101 cmmTypeSize ty 
102         | isFloatType ty        = floatSize (typeWidth ty)
103         | otherwise             = intSize (typeWidth ty)
104
105
106 sizeToWidth :: Size -> Width
107 sizeToWidth II8  = W8
108 sizeToWidth II16 = W16
109 sizeToWidth II32 = W32
110 sizeToWidth II64 = W64
111 sizeToWidth FF32 = W32
112 sizeToWidth FF64 = W64
113 sizeToWidth _ = panic "MachInstrs.sizeToWidth"
114
115
116 mkVReg :: Unique -> Size -> Reg
117 mkVReg u size
118    | not (isFloatSize size) = VirtualRegI u
119    | otherwise
120    = case size of
121         FF32    -> VirtualRegD u
122         FF64    -> VirtualRegD u
123         _       -> panic "mkVReg"
124
125
126
127 -- immediates ------------------------------------------------------------------
128 data Imm
129         = ImmInt        Int
130         | ImmInteger    Integer     -- Sigh.
131         | ImmCLbl       CLabel      -- AbstractC Label (with baggage)
132         | ImmLit        Doc         -- Simple string
133         | ImmIndex    CLabel Int
134         | ImmFloat      Rational
135         | ImmDouble     Rational
136         | ImmConstantSum Imm Imm
137         | ImmConstantDiff Imm Imm
138         | LO Imm
139         | HI Imm
140         | HA Imm        {- high halfword adjusted -}
141
142
143 strImmLit :: String -> Imm
144 strImmLit s = ImmLit (text s)
145
146
147 litToImm :: CmmLit -> Imm
148 litToImm (CmmInt i w)        = ImmInteger (narrowS w i)
149                 -- narrow to the width: a CmmInt might be out of
150                 -- range, but we assume that ImmInteger only contains
151                 -- in-range values.  A signed value should be fine here.
152 litToImm (CmmFloat f W32)    = ImmFloat f
153 litToImm (CmmFloat f W64)    = ImmDouble f
154 litToImm (CmmLabel l)        = ImmCLbl l
155 litToImm (CmmLabelOff l off) = ImmIndex l off
156 litToImm (CmmLabelDiffOff l1 l2 off)
157                              = ImmConstantSum
158                                (ImmConstantDiff (ImmCLbl l1) (ImmCLbl l2))
159                                (ImmInt off)
160 litToImm (CmmBlock id)       = ImmCLbl (infoTblLbl id)
161 litToImm _                   = panic "PPC.Regs.litToImm: no match"
162
163
164 -- addressing modes ------------------------------------------------------------
165
166 data AddrMode
167         = AddrRegReg    Reg Reg
168         | AddrRegImm    Reg Imm
169
170
171 addrOffset :: AddrMode -> Int -> Maybe AddrMode
172 addrOffset addr off
173   = case addr of
174       AddrRegImm r (ImmInt n)
175        | fits16Bits n2 -> Just (AddrRegImm r (ImmInt n2))
176        | otherwise     -> Nothing
177        where n2 = n + off
178
179       AddrRegImm r (ImmInteger n)
180        | fits16Bits n2 -> Just (AddrRegImm r (ImmInt (fromInteger n2)))
181        | otherwise     -> Nothing
182        where n2 = n + toInteger off
183        
184       _ -> Nothing
185
186
187 -- registers -------------------------------------------------------------------
188 -- @spRel@ gives us a stack relative addressing mode for volatile
189 -- temporaries and for excess call arguments.  @fpRel@, where
190 -- applicable, is the same but for the frame pointer.
191
192 spRel :: Int    -- desired stack offset in words, positive or negative
193       -> AddrMode
194
195 spRel n = AddrRegImm sp (ImmInt (n * wORD_SIZE))
196
197
198 -- argRegs is the set of regs which are read for an n-argument call to C.
199 -- For archs which pass all args on the stack (x86), is empty.
200 -- Sparc passes up to the first 6 args in regs.
201 -- Dunno about Alpha.
202 argRegs :: RegNo -> [Reg]
203 argRegs 0 = []
204 argRegs 1 = map RealReg [3]
205 argRegs 2 = map RealReg [3,4]
206 argRegs 3 = map RealReg [3..5]
207 argRegs 4 = map RealReg [3..6]
208 argRegs 5 = map RealReg [3..7]
209 argRegs 6 = map RealReg [3..8]
210 argRegs 7 = map RealReg [3..9]
211 argRegs 8 = map RealReg [3..10]
212 argRegs _ = panic "MachRegs.argRegs(powerpc): don't know about >8 arguments!"
213
214
215 allArgRegs :: [Reg]
216 allArgRegs = map RealReg [3..10]
217
218
219 -- these are the regs which we cannot assume stay alive over a C call.  
220 callClobberedRegs :: [Reg]
221 #if   defined(darwin_TARGET_OS)
222 callClobberedRegs
223   = map RealReg (0:[2..12] ++ map fReg [0..13])
224
225 #elif defined(linux_TARGET_OS)
226 callClobberedRegs
227   = map RealReg (0:[2..13] ++ map fReg [0..13])
228
229 #else
230 callClobberedRegs
231         = panic "PPC.Regs.callClobberedRegs: not defined for this architecture"
232 #endif
233
234
235 allMachRegNos   :: [RegNo]
236 allMachRegNos   = [0..63]
237
238
239 {-# INLINE regClass      #-}
240 regClass :: Reg -> RegClass
241 regClass (VirtualRegI  _) = RcInteger
242 regClass (VirtualRegHi _) = RcInteger
243 regClass (VirtualRegF  u) = pprPanic ("regClass(ppc):VirtualRegF ") (ppr u)
244 regClass (VirtualRegD  _) = RcDouble
245 regClass (RealReg i) 
246         | i < 32        = RcInteger 
247         | otherwise     = RcDouble
248
249
250 showReg :: RegNo -> String
251 showReg n
252     | n >= 0 && n <= 31   = "%r" ++ show n
253     | n >= 32 && n <= 63  = "%f" ++ show (n - 32)
254     | otherwise           = "%unknown_powerpc_real_reg_" ++ show n
255
256
257
258 -- machine specific ------------------------------------------------------------
259
260 allFPArgRegs :: [Reg]
261 #if    defined(darwin_TARGET_OS)
262 allFPArgRegs = map (RealReg . fReg) [1..13]
263
264 #elif  defined(linux_TARGET_OS)
265 allFPArgRegs = map (RealReg . fReg) [1..8]
266
267 #else
268 allFPArgRegs = panic "PPC.Regs.allFPArgRegs: not defined for this architecture"
269
270 #endif
271
272 fits16Bits :: Integral a => a -> Bool
273 fits16Bits x = x >= -32768 && x < 32768
274
275 makeImmediate :: Integral a => Width -> Bool -> a -> Maybe Imm
276 makeImmediate rep signed x = fmap ImmInt (toI16 rep signed)
277     where
278         narrow W32 False = fromIntegral (fromIntegral x :: Word32)
279         narrow W16 False = fromIntegral (fromIntegral x :: Word16)
280         narrow W8  False = fromIntegral (fromIntegral x :: Word8)
281         narrow W32 True  = fromIntegral (fromIntegral x :: Int32)
282         narrow W16 True  = fromIntegral (fromIntegral x :: Int16)
283         narrow W8  True  = fromIntegral (fromIntegral x :: Int8)
284         narrow _   _     = panic "PPC.Regs.narrow: no match"
285         
286         narrowed = narrow rep signed
287         
288         toI16 W32 True
289             | narrowed >= -32768 && narrowed < 32768 = Just narrowed
290             | otherwise = Nothing
291         toI16 W32 False
292             | narrowed >= 0 && narrowed < 65536 = Just narrowed
293             | otherwise = Nothing
294         toI16 _ _  = Just narrowed
295
296
297 {-
298 The PowerPC has 64 registers of interest; 32 integer registers and 32 floating
299 point registers.
300 -}
301
302 fReg :: Int -> RegNo
303 fReg x = (32 + x)
304
305 sp, r3, r4, r27, r28, f1, f20, f21 :: Reg
306 sp      = RealReg 1
307 r3      = RealReg 3
308 r4      = RealReg 4
309 r27     = RealReg 27
310 r28     = RealReg 28
311 f1      = RealReg $ fReg 1
312 f20     = RealReg $ fReg 20
313 f21     = RealReg $ fReg 21
314
315
316
317 -- horror show -----------------------------------------------------------------
318 freeReg :: RegNo -> FastBool
319 globalRegMaybe :: GlobalReg -> Maybe Reg
320
321
322 #if powerpc_TARGET_ARCH
323 #define r0 0
324 #define r1 1
325 #define r2 2
326 #define r3 3
327 #define r4 4
328 #define r5 5
329 #define r6 6
330 #define r7 7
331 #define r8 8
332 #define r9 9
333 #define r10 10
334 #define r11 11
335 #define r12 12
336 #define r13 13
337 #define r14 14
338 #define r15 15
339 #define r16 16
340 #define r17 17
341 #define r18 18
342 #define r19 19
343 #define r20 20
344 #define r21 21
345 #define r22 22
346 #define r23 23
347 #define r24 24
348 #define r25 25
349 #define r26 26
350 #define r27 27
351 #define r28 28
352 #define r29 29
353 #define r30 30
354 #define r31 31
355
356 #ifdef darwin_TARGET_OS
357 #define f0  32
358 #define f1  33
359 #define f2  34
360 #define f3  35
361 #define f4  36
362 #define f5  37
363 #define f6  38
364 #define f7  39
365 #define f8  40
366 #define f9  41
367 #define f10 42
368 #define f11 43
369 #define f12 44
370 #define f13 45
371 #define f14 46
372 #define f15 47
373 #define f16 48
374 #define f17 49
375 #define f18 50
376 #define f19 51
377 #define f20 52
378 #define f21 53
379 #define f22 54
380 #define f23 55
381 #define f24 56
382 #define f25 57
383 #define f26 58
384 #define f27 59
385 #define f28 60
386 #define f29 61
387 #define f30 62
388 #define f31 63
389 #else
390 #define fr0  32
391 #define fr1  33
392 #define fr2  34
393 #define fr3  35
394 #define fr4  36
395 #define fr5  37
396 #define fr6  38
397 #define fr7  39
398 #define fr8  40
399 #define fr9  41
400 #define fr10 42
401 #define fr11 43
402 #define fr12 44
403 #define fr13 45
404 #define fr14 46
405 #define fr15 47
406 #define fr16 48
407 #define fr17 49
408 #define fr18 50
409 #define fr19 51
410 #define fr20 52
411 #define fr21 53
412 #define fr22 54
413 #define fr23 55
414 #define fr24 56
415 #define fr25 57
416 #define fr26 58
417 #define fr27 59
418 #define fr28 60
419 #define fr29 61
420 #define fr30 62
421 #define fr31 63
422 #endif
423
424
425
426 freeReg 0 = fastBool False -- Hack: r0 can't be used in all insns, but it's actually free
427 freeReg 1 = fastBool False -- The Stack Pointer
428 #if !darwin_TARGET_OS
429  -- most non-darwin powerpc OSes use r2 as a TOC pointer or something like that
430 freeReg 2 = fastBool False
431 #endif
432
433 #ifdef REG_Base
434 freeReg REG_Base = fastBool False
435 #endif
436 #ifdef REG_R1
437 freeReg REG_R1   = fastBool False
438 #endif  
439 #ifdef REG_R2  
440 freeReg REG_R2   = fastBool False
441 #endif  
442 #ifdef REG_R3  
443 freeReg REG_R3   = fastBool False
444 #endif  
445 #ifdef REG_R4  
446 freeReg REG_R4   = fastBool False
447 #endif  
448 #ifdef REG_R5  
449 freeReg REG_R5   = fastBool False
450 #endif  
451 #ifdef REG_R6  
452 freeReg REG_R6   = fastBool False
453 #endif  
454 #ifdef REG_R7  
455 freeReg REG_R7   = fastBool False
456 #endif  
457 #ifdef REG_R8  
458 freeReg REG_R8   = fastBool False
459 #endif
460 #ifdef REG_F1
461 freeReg REG_F1 = fastBool False
462 #endif
463 #ifdef REG_F2
464 freeReg REG_F2 = fastBool False
465 #endif
466 #ifdef REG_F3
467 freeReg REG_F3 = fastBool False
468 #endif
469 #ifdef REG_F4
470 freeReg REG_F4 = fastBool False
471 #endif
472 #ifdef REG_D1
473 freeReg REG_D1 = fastBool False
474 #endif
475 #ifdef REG_D2
476 freeReg REG_D2 = fastBool False
477 #endif
478 #ifdef REG_Sp 
479 freeReg REG_Sp   = fastBool False
480 #endif 
481 #ifdef REG_Su
482 freeReg REG_Su   = fastBool False
483 #endif 
484 #ifdef REG_SpLim 
485 freeReg REG_SpLim = fastBool False
486 #endif 
487 #ifdef REG_Hp 
488 freeReg REG_Hp   = fastBool False
489 #endif
490 #ifdef REG_HpLim
491 freeReg REG_HpLim = fastBool False
492 #endif
493 freeReg _               = fastBool True
494
495
496 --  | Returns 'Nothing' if this global register is not stored
497 -- in a real machine register, otherwise returns @'Just' reg@, where
498 -- reg is the machine register it is stored in.
499
500
501 #ifdef REG_Base
502 globalRegMaybe BaseReg                  = Just (RealReg REG_Base)
503 #endif
504 #ifdef REG_R1
505 globalRegMaybe (VanillaReg 1 _)         = Just (RealReg REG_R1)
506 #endif 
507 #ifdef REG_R2 
508 globalRegMaybe (VanillaReg 2 _)         = Just (RealReg REG_R2)
509 #endif 
510 #ifdef REG_R3 
511 globalRegMaybe (VanillaReg 3 _)         = Just (RealReg REG_R3)
512 #endif 
513 #ifdef REG_R4 
514 globalRegMaybe (VanillaReg 4 _)         = Just (RealReg REG_R4)
515 #endif 
516 #ifdef REG_R5 
517 globalRegMaybe (VanillaReg 5 _)         = Just (RealReg REG_R5)
518 #endif 
519 #ifdef REG_R6 
520 globalRegMaybe (VanillaReg 6 _)         = Just (RealReg REG_R6)
521 #endif 
522 #ifdef REG_R7 
523 globalRegMaybe (VanillaReg 7 _)         = Just (RealReg REG_R7)
524 #endif 
525 #ifdef REG_R8 
526 globalRegMaybe (VanillaReg 8 _)         = Just (RealReg REG_R8)
527 #endif
528 #ifdef REG_R9 
529 globalRegMaybe (VanillaReg 9 _)         = Just (RealReg REG_R9)
530 #endif
531 #ifdef REG_R10 
532 globalRegMaybe (VanillaReg 10 _)        = Just (RealReg REG_R10)
533 #endif
534 #ifdef REG_F1
535 globalRegMaybe (FloatReg 1)             = Just (RealReg REG_F1)
536 #endif                                  
537 #ifdef REG_F2                           
538 globalRegMaybe (FloatReg 2)             = Just (RealReg REG_F2)
539 #endif                                  
540 #ifdef REG_F3                           
541 globalRegMaybe (FloatReg 3)             = Just (RealReg REG_F3)
542 #endif                                  
543 #ifdef REG_F4                           
544 globalRegMaybe (FloatReg 4)             = Just (RealReg REG_F4)
545 #endif                                  
546 #ifdef REG_D1                           
547 globalRegMaybe (DoubleReg 1)            = Just (RealReg REG_D1)
548 #endif                                  
549 #ifdef REG_D2                           
550 globalRegMaybe (DoubleReg 2)            = Just (RealReg REG_D2)
551 #endif
552 #ifdef REG_Sp       
553 globalRegMaybe Sp                       = Just (RealReg REG_Sp)
554 #endif
555 #ifdef REG_Lng1                         
556 globalRegMaybe (LongReg 1)              = Just (RealReg REG_Lng1)
557 #endif                                  
558 #ifdef REG_Lng2                         
559 globalRegMaybe (LongReg 2)              = Just (RealReg REG_Lng2)
560 #endif
561 #ifdef REG_SpLim                                
562 globalRegMaybe SpLim                    = Just (RealReg REG_SpLim)
563 #endif                                  
564 #ifdef REG_Hp                           
565 globalRegMaybe Hp                       = Just (RealReg REG_Hp)
566 #endif                                  
567 #ifdef REG_HpLim                        
568 globalRegMaybe HpLim                    = Just (RealReg REG_HpLim)
569 #endif                                  
570 #ifdef REG_CurrentTSO                           
571 globalRegMaybe CurrentTSO               = Just (RealReg REG_CurrentTSO)
572 #endif                                  
573 #ifdef REG_CurrentNursery                       
574 globalRegMaybe CurrentNursery           = Just (RealReg REG_CurrentNursery)
575 #endif                                  
576 globalRegMaybe _                        = Nothing
577
578
579 #else  /* powerpc_TARGET_ARCH */
580
581 freeReg _               = 0#
582 globalRegMaybe _        = panic "PPC.Regs.globalRegMaybe: not defined"
583
584 #endif /* powerpc_TARGET_ARCH */