SPARC NCG: Enumerate freeRegs / globalRegMaybe instead of using #ifdefery
[ghc.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 n = 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 */