c39313a6f2f5bd454122b19b93d3597450358c3f
[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 -- 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 regSingle [3]
142 argRegs 2 = map regSingle [3,4]
143 argRegs 3 = map regSingle [3..5]
144 argRegs 4 = map regSingle [3..6]
145 argRegs 5 = map regSingle [3..7]
146 argRegs 6 = map regSingle [3..8]
147 argRegs 7 = map regSingle [3..9]
148 argRegs 8 = map regSingle [3..10]
149 argRegs _ = panic "MachRegs.argRegs(powerpc): don't know about >8 arguments!"
150
151
152 allArgRegs :: [Reg]
153 allArgRegs = map regSingle [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 regSingle (0:[2..12] ++ map fReg [0..13])
161
162 #elif defined(linux_TARGET_OS)
163 callClobberedRegs
164 = map regSingle (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 (RegVirtual (VirtualRegI _)) = RcInteger
179 regClass (RegVirtual (VirtualRegHi _)) = RcInteger
180 regClass (RegVirtual (VirtualRegF u)) = pprPanic ("regClass(ppc):VirtualRegF ") (ppr u)
181 regClass (RegVirtual (VirtualRegD _)) = RcDouble
182
183 regClass (RegReal (RealRegSingle i))
184 | i < 32 = RcInteger
185 | otherwise = RcDouble
186
187 regClass (RegReal (RealRegPair{}))
188 = panic "regClass(ppr): no reg pairs on this architecture"
189
190 showReg :: RegNo -> String
191 showReg n
192 | n >= 0 && n <= 31 = "%r" ++ show n
193 | n >= 32 && n <= 63 = "%f" ++ show (n - 32)
194 | otherwise = "%unknown_powerpc_real_reg_" ++ show n
195
196
197
198 -- machine specific ------------------------------------------------------------
199
200 allFPArgRegs :: [Reg]
201 #if defined(darwin_TARGET_OS)
202 allFPArgRegs = map (regSingle . fReg) [1..13]
203
204 #elif defined(linux_TARGET_OS)
205 allFPArgRegs = map (regSingle . fReg) [1..8]
206
207 #else
208 allFPArgRegs = panic "PPC.Regs.allFPArgRegs: not defined for this architecture"
209
210 #endif
211
212 fits16Bits :: Integral a => a -> Bool
213 fits16Bits x = x >= -32768 && x < 32768
214
215 makeImmediate :: Integral a => Width -> Bool -> a -> Maybe Imm
216 makeImmediate rep signed x = fmap ImmInt (toI16 rep signed)
217 where
218 narrow W32 False = fromIntegral (fromIntegral x :: Word32)
219 narrow W16 False = fromIntegral (fromIntegral x :: Word16)
220 narrow W8 False = fromIntegral (fromIntegral x :: Word8)
221 narrow W32 True = fromIntegral (fromIntegral x :: Int32)
222 narrow W16 True = fromIntegral (fromIntegral x :: Int16)
223 narrow W8 True = fromIntegral (fromIntegral x :: Int8)
224 narrow _ _ = panic "PPC.Regs.narrow: no match"
225
226 narrowed = narrow rep signed
227
228 toI16 W32 True
229 | narrowed >= -32768 && narrowed < 32768 = Just narrowed
230 | otherwise = Nothing
231 toI16 W32 False
232 | narrowed >= 0 && narrowed < 65536 = Just narrowed
233 | otherwise = Nothing
234 toI16 _ _ = Just narrowed
235
236
237 {-
238 The PowerPC has 64 registers of interest; 32 integer registers and 32 floating
239 point registers.
240 -}
241
242 fReg :: Int -> RegNo
243 fReg x = (32 + x)
244
245 sp, r3, r4, r27, r28, f1, f20, f21 :: Reg
246 sp = regSingle 1
247 r3 = regSingle 3
248 r4 = regSingle 4
249 r27 = regSingle 27
250 r28 = regSingle 28
251 f1 = regSingle $ fReg 1
252 f20 = regSingle $ fReg 20
253 f21 = regSingle $ fReg 21
254
255
256
257 -- horror show -----------------------------------------------------------------
258 freeReg :: RegNo -> FastBool
259 globalRegMaybe :: GlobalReg -> Maybe Reg
260
261
262 #if powerpc_TARGET_ARCH
263 #define r0 0
264 #define r1 1
265 #define r2 2
266 #define r3 3
267 #define r4 4
268 #define r5 5
269 #define r6 6
270 #define r7 7
271 #define r8 8
272 #define r9 9
273 #define r10 10
274 #define r11 11
275 #define r12 12
276 #define r13 13
277 #define r14 14
278 #define r15 15
279 #define r16 16
280 #define r17 17
281 #define r18 18
282 #define r19 19
283 #define r20 20
284 #define r21 21
285 #define r22 22
286 #define r23 23
287 #define r24 24
288 #define r25 25
289 #define r26 26
290 #define r27 27
291 #define r28 28
292 #define r29 29
293 #define r30 30
294 #define r31 31
295
296 #ifdef darwin_TARGET_OS
297 #define f0 32
298 #define f1 33
299 #define f2 34
300 #define f3 35
301 #define f4 36
302 #define f5 37
303 #define f6 38
304 #define f7 39
305 #define f8 40
306 #define f9 41
307 #define f10 42
308 #define f11 43
309 #define f12 44
310 #define f13 45
311 #define f14 46
312 #define f15 47
313 #define f16 48
314 #define f17 49
315 #define f18 50
316 #define f19 51
317 #define f20 52
318 #define f21 53
319 #define f22 54
320 #define f23 55
321 #define f24 56
322 #define f25 57
323 #define f26 58
324 #define f27 59
325 #define f28 60
326 #define f29 61
327 #define f30 62
328 #define f31 63
329 #else
330 #define fr0 32
331 #define fr1 33
332 #define fr2 34
333 #define fr3 35
334 #define fr4 36
335 #define fr5 37
336 #define fr6 38
337 #define fr7 39
338 #define fr8 40
339 #define fr9 41
340 #define fr10 42
341 #define fr11 43
342 #define fr12 44
343 #define fr13 45
344 #define fr14 46
345 #define fr15 47
346 #define fr16 48
347 #define fr17 49
348 #define fr18 50
349 #define fr19 51
350 #define fr20 52
351 #define fr21 53
352 #define fr22 54
353 #define fr23 55
354 #define fr24 56
355 #define fr25 57
356 #define fr26 58
357 #define fr27 59
358 #define fr28 60
359 #define fr29 61
360 #define fr30 62
361 #define fr31 63
362 #endif
363
364
365
366 freeReg 0 = fastBool False -- Hack: r0 can't be used in all insns, but it's actually free
367 freeReg 1 = fastBool False -- The Stack Pointer
368 #if !darwin_TARGET_OS
369 -- most non-darwin powerpc OSes use r2 as a TOC pointer or something like that
370 freeReg 2 = fastBool False
371 #endif
372
373 #ifdef REG_Base
374 freeReg REG_Base = fastBool False
375 #endif
376 #ifdef REG_R1
377 freeReg REG_R1 = fastBool False
378 #endif
379 #ifdef REG_R2
380 freeReg REG_R2 = fastBool False
381 #endif
382 #ifdef REG_R3
383 freeReg REG_R3 = fastBool False
384 #endif
385 #ifdef REG_R4
386 freeReg REG_R4 = fastBool False
387 #endif
388 #ifdef REG_R5
389 freeReg REG_R5 = fastBool False
390 #endif
391 #ifdef REG_R6
392 freeReg REG_R6 = fastBool False
393 #endif
394 #ifdef REG_R7
395 freeReg REG_R7 = fastBool False
396 #endif
397 #ifdef REG_R8
398 freeReg REG_R8 = fastBool False
399 #endif
400 #ifdef REG_F1
401 freeReg REG_F1 = fastBool False
402 #endif
403 #ifdef REG_F2
404 freeReg REG_F2 = fastBool False
405 #endif
406 #ifdef REG_F3
407 freeReg REG_F3 = fastBool False
408 #endif
409 #ifdef REG_F4
410 freeReg REG_F4 = fastBool False
411 #endif
412 #ifdef REG_D1
413 freeReg REG_D1 = fastBool False
414 #endif
415 #ifdef REG_D2
416 freeReg REG_D2 = fastBool False
417 #endif
418 #ifdef REG_Sp
419 freeReg REG_Sp = fastBool False
420 #endif
421 #ifdef REG_Su
422 freeReg REG_Su = fastBool False
423 #endif
424 #ifdef REG_SpLim
425 freeReg REG_SpLim = fastBool False
426 #endif
427 #ifdef REG_Hp
428 freeReg REG_Hp = fastBool False
429 #endif
430 #ifdef REG_HpLim
431 freeReg REG_HpLim = fastBool False
432 #endif
433 freeReg _ = fastBool True
434
435
436 -- | Returns 'Nothing' if this global register is not stored
437 -- in a real machine register, otherwise returns @'Just' reg@, where
438 -- reg is the machine register it is stored in.
439
440
441 #ifdef REG_Base
442 globalRegMaybe BaseReg = Just (regSingle REG_Base)
443 #endif
444 #ifdef REG_R1
445 globalRegMaybe (VanillaReg 1 _) = Just (regSingle REG_R1)
446 #endif
447 #ifdef REG_R2
448 globalRegMaybe (VanillaReg 2 _) = Just (regSingle REG_R2)
449 #endif
450 #ifdef REG_R3
451 globalRegMaybe (VanillaReg 3 _) = Just (regSingle REG_R3)
452 #endif
453 #ifdef REG_R4
454 globalRegMaybe (VanillaReg 4 _) = Just (regSingle REG_R4)
455 #endif
456 #ifdef REG_R5
457 globalRegMaybe (VanillaReg 5 _) = Just (regSingle REG_R5)
458 #endif
459 #ifdef REG_R6
460 globalRegMaybe (VanillaReg 6 _) = Just (regSingle REG_R6)
461 #endif
462 #ifdef REG_R7
463 globalRegMaybe (VanillaReg 7 _) = Just (regSingle REG_R7)
464 #endif
465 #ifdef REG_R8
466 globalRegMaybe (VanillaReg 8 _) = Just (regSingle REG_R8)
467 #endif
468 #ifdef REG_R9
469 globalRegMaybe (VanillaReg 9 _) = Just (regSingle REG_R9)
470 #endif
471 #ifdef REG_R10
472 globalRegMaybe (VanillaReg 10 _) = Just (regSingle REG_R10)
473 #endif
474 #ifdef REG_F1
475 globalRegMaybe (FloatReg 1) = Just (regSingle REG_F1)
476 #endif
477 #ifdef REG_F2
478 globalRegMaybe (FloatReg 2) = Just (regSingle REG_F2)
479 #endif
480 #ifdef REG_F3
481 globalRegMaybe (FloatReg 3) = Just (regSingle REG_F3)
482 #endif
483 #ifdef REG_F4
484 globalRegMaybe (FloatReg 4) = Just (regSingle REG_F4)
485 #endif
486 #ifdef REG_D1
487 globalRegMaybe (DoubleReg 1) = Just (regSingle REG_D1)
488 #endif
489 #ifdef REG_D2
490 globalRegMaybe (DoubleReg 2) = Just (regSingle REG_D2)
491 #endif
492 #ifdef REG_Sp
493 globalRegMaybe Sp = Just (regSingle REG_Sp)
494 #endif
495 #ifdef REG_Lng1
496 globalRegMaybe (LongReg 1) = Just (regSingle REG_Lng1)
497 #endif
498 #ifdef REG_Lng2
499 globalRegMaybe (LongReg 2) = Just (regSingle REG_Lng2)
500 #endif
501 #ifdef REG_SpLim
502 globalRegMaybe SpLim = Just (regSingle REG_SpLim)
503 #endif
504 #ifdef REG_Hp
505 globalRegMaybe Hp = Just (regSingle REG_Hp)
506 #endif
507 #ifdef REG_HpLim
508 globalRegMaybe HpLim = Just (regSingle REG_HpLim)
509 #endif
510 #ifdef REG_CurrentTSO
511 globalRegMaybe CurrentTSO = Just (regSingle REG_CurrentTSO)
512 #endif
513 #ifdef REG_CurrentNursery
514 globalRegMaybe CurrentNursery = Just (regSingle REG_CurrentNursery)
515 #endif
516 globalRegMaybe _ = Nothing
517
518
519 #else /* powerpc_TARGET_ARCH */
520
521 freeReg _ = 0#
522 globalRegMaybe _ = panic "PPC.Regs.globalRegMaybe: not defined"
523
524 #endif /* powerpc_TARGET_ARCH */
525
526
527 -- We map STG registers onto appropriate CmmExprs. Either they map
528 -- to real machine registers or stored as offsets from BaseReg. Given
529 -- a GlobalReg, get_GlobalReg_reg_or_addr produces either the real
530 -- register it is in, on this platform, or a CmmExpr denoting the
531 -- address in the register table holding it.
532 -- (See also get_GlobalReg_addr in CgUtils.)
533
534 get_GlobalReg_reg_or_addr :: GlobalReg -> Either Reg CmmExpr
535 get_GlobalReg_reg_or_addr mid
536 = case globalRegMaybe mid of
537 Just rr -> Left rr
538 Nothing -> Right (get_GlobalReg_addr mid)
539
540
541 -- allocatableRegs is allMachRegNos with the fixed-use regs removed.
542 -- i.e., these are the regs for which we are prepared to allow the
543 -- register allocator to attempt to map VRegs to.
544 allocatableRegs :: [RegNo]
545 allocatableRegs
546 = let isFree i = isFastTrue (freeReg i)
547 in filter isFree allMachRegNos