NCG: Split PprMach into arch specific modules
[ghc-hetmet.git] / compiler / nativeGen / PPC / Ppr.hs
1 -----------------------------------------------------------------------------
2 --
3 -- Pretty-printing assembly language
4 --
5 -- (c) The University of Glasgow 1993-2005
6 --
7 -----------------------------------------------------------------------------
8
9 module PPC.Ppr (
10         pprUserReg,
11         pprSize,
12         pprImm,
13         pprSectionHeader,
14         pprDataItem,
15         pprInstr
16 )
17
18 where
19
20 #include "nativeGen/NCG.h"
21 #include "HsVersions.h"
22
23 import RegsBase
24 import PprBase
25 import PPC.Regs
26 import PPC.Instr
27
28 import BlockId
29 import Cmm
30
31 import CLabel           ( mkAsmTempLabel )
32
33 import Unique           ( pprUnique )
34 import Pretty
35 import FastString
36 import qualified Outputable
37 import Outputable       ( panic )
38
39 import Data.Word(Word32)
40 import Data.Bits
41
42
43 pprUserReg :: Reg -> Doc
44 pprUserReg = pprReg
45
46 pprReg :: Reg -> Doc
47
48 pprReg r
49   = case r of
50       RealReg i      -> ppr_reg_no i
51       VirtualRegI  u  -> text "%vI_" <> asmSDoc (pprUnique u)
52       VirtualRegHi u  -> text "%vHi_" <> asmSDoc (pprUnique u)
53       VirtualRegF  u  -> text "%vF_" <> asmSDoc (pprUnique u)
54       VirtualRegD  u  -> text "%vD_" <> asmSDoc (pprUnique u)
55   where
56 #if darwin_TARGET_OS
57     ppr_reg_no :: Int -> Doc
58     ppr_reg_no i = ptext
59       (case i of {
60          0 -> sLit "r0";   1 -> sLit "r1";
61          2 -> sLit "r2";   3 -> sLit "r3";
62          4 -> sLit "r4";   5 -> sLit "r5";
63          6 -> sLit "r6";   7 -> sLit "r7";
64          8 -> sLit "r8";   9 -> sLit "r9";
65         10 -> sLit "r10";  11 -> sLit "r11";
66         12 -> sLit "r12";  13 -> sLit "r13";
67         14 -> sLit "r14";  15 -> sLit "r15";
68         16 -> sLit "r16";  17 -> sLit "r17";
69         18 -> sLit "r18";  19 -> sLit "r19";
70         20 -> sLit "r20";  21 -> sLit "r21";
71         22 -> sLit "r22";  23 -> sLit "r23";
72         24 -> sLit "r24";  25 -> sLit "r25";
73         26 -> sLit "r26";  27 -> sLit "r27";
74         28 -> sLit "r28";  29 -> sLit "r29";
75         30 -> sLit "r30";  31 -> sLit "r31";
76         32 -> sLit "f0";  33 -> sLit "f1";
77         34 -> sLit "f2";  35 -> sLit "f3";
78         36 -> sLit "f4";  37 -> sLit "f5";
79         38 -> sLit "f6";  39 -> sLit "f7";
80         40 -> sLit "f8";  41 -> sLit "f9";
81         42 -> sLit "f10"; 43 -> sLit "f11";
82         44 -> sLit "f12"; 45 -> sLit "f13";
83         46 -> sLit "f14"; 47 -> sLit "f15";
84         48 -> sLit "f16"; 49 -> sLit "f17";
85         50 -> sLit "f18"; 51 -> sLit "f19";
86         52 -> sLit "f20"; 53 -> sLit "f21";
87         54 -> sLit "f22"; 55 -> sLit "f23";
88         56 -> sLit "f24"; 57 -> sLit "f25";
89         58 -> sLit "f26"; 59 -> sLit "f27";
90         60 -> sLit "f28"; 61 -> sLit "f29";
91         62 -> sLit "f30"; 63 -> sLit "f31";
92         _  -> sLit "very naughty powerpc register"
93       })
94 #else
95     ppr_reg_no :: Int -> Doc
96     ppr_reg_no i | i <= 31 = int i      -- GPRs
97                  | i <= 63 = int (i-32) -- FPRs
98                  | otherwise = ptext (sLit "very naughty powerpc register")
99 #endif
100
101
102
103 pprSize :: Size -> Doc
104 pprSize x 
105  = ptext (case x of
106                 II8     -> sLit "b"
107                 II16    -> sLit "h"
108                 II32    -> sLit "w"
109                 FF32    -> sLit "fs"
110                 FF64    -> sLit "fd"
111                 _       -> panic "PPC.Ppr.pprSize: no match")
112                 
113                 
114 pprCond :: Cond -> Doc
115 pprCond c 
116  = ptext (case c of {
117                 ALWAYS  -> sLit "";
118                 EQQ     -> sLit "eq";   NE    -> sLit "ne";
119                 LTT     -> sLit "lt";  GE    -> sLit "ge";
120                 GTT     -> sLit "gt";  LE    -> sLit "le";
121                 LU      -> sLit "lt";  GEU   -> sLit "ge";
122                 GU      -> sLit "gt";  LEU   -> sLit "le"; })
123
124
125 pprImm :: Imm -> Doc
126
127 pprImm (ImmInt i)     = int i
128 pprImm (ImmInteger i) = integer i
129 pprImm (ImmCLbl l)    = pprCLabel_asm l
130 pprImm (ImmIndex l i) = pprCLabel_asm l <> char '+' <> int i
131 pprImm (ImmLit s)     = s
132
133 pprImm (ImmFloat _)  = ptext (sLit "naughty float immediate")
134 pprImm (ImmDouble _) = ptext (sLit "naughty double immediate")
135
136 pprImm (ImmConstantSum a b) = pprImm a <> char '+' <> pprImm b
137 pprImm (ImmConstantDiff a b) = pprImm a <> char '-'
138                             <> lparen <> pprImm b <> rparen
139
140 #if darwin_TARGET_OS
141 pprImm (LO i)
142   = hcat [ pp_lo, pprImm i, rparen ]
143   where
144     pp_lo = text "lo16("
145
146 pprImm (HI i)
147   = hcat [ pp_hi, pprImm i, rparen ]
148   where
149     pp_hi = text "hi16("
150
151 pprImm (HA i)
152   = hcat [ pp_ha, pprImm i, rparen ]
153   where
154     pp_ha = text "ha16("
155     
156 #else
157 pprImm (LO i)
158   = pprImm i <> text "@l"
159
160 pprImm (HI i)
161   = pprImm i <> text "@h"
162
163 pprImm (HA i)
164   = pprImm i <> text "@ha"
165 #endif
166
167
168
169 pprAddr :: AddrMode -> Doc
170 pprAddr (AddrRegReg r1 r2)
171   = pprReg r1 <+> ptext (sLit ", ") <+> pprReg r2
172
173 pprAddr (AddrRegImm r1 (ImmInt i)) = hcat [ int i, char '(', pprReg r1, char ')' ]
174 pprAddr (AddrRegImm r1 (ImmInteger i)) = hcat [ integer i, char '(', pprReg r1, char ')' ]
175 pprAddr (AddrRegImm r1 imm) = hcat [ pprImm imm, char '(', pprReg r1, char ')' ]
176
177
178 pprSectionHeader :: Section -> Doc
179 #if darwin_TARGET_OS 
180 pprSectionHeader seg
181  = case seg of
182         Text                    -> ptext (sLit ".text\n.align 2")
183         Data                    -> ptext (sLit ".data\n.align 2")
184         ReadOnlyData            -> ptext (sLit ".const\n.align 2")
185         RelocatableReadOnlyData -> ptext (sLit ".const_data\n.align 2")
186         UninitialisedData       -> ptext (sLit ".const_data\n.align 2")
187         ReadOnlyData16          -> ptext (sLit ".const\n.align 4")
188         OtherSection _          -> panic "PprMach.pprSectionHeader: unknown section"
189
190 #else
191 pprSectionHeader seg
192  = case seg of
193         Text                    -> ptext (sLit ".text\n.align 2")
194         Data                    -> ptext (sLit ".data\n.align 2")
195         ReadOnlyData            -> ptext (sLit ".section .rodata\n\t.align 2")
196         RelocatableReadOnlyData -> ptext (sLit ".data\n\t.align 2")
197         UninitialisedData       -> ptext (sLit ".section .bss\n\t.align 2")
198         ReadOnlyData16          -> ptext (sLit ".section .rodata\n\t.align 4")
199         OtherSection _          -> panic "PprMach.pprSectionHeader: unknown section"
200
201 #endif
202
203
204 pprDataItem :: CmmLit -> Doc
205 pprDataItem lit
206   = vcat (ppr_item (cmmTypeSize $ cmmLitType lit) lit)
207     where
208         imm = litToImm lit
209
210         ppr_item II8   _ = [ptext (sLit "\t.byte\t") <> pprImm imm]
211
212         ppr_item II32  _ = [ptext (sLit "\t.long\t") <> pprImm imm]
213
214         ppr_item FF32 (CmmFloat r _)
215            = let bs = floatToBytes (fromRational r)
216              in  map (\b -> ptext (sLit "\t.byte\t") <> pprImm (ImmInt b)) bs
217
218         ppr_item FF64 (CmmFloat r _)
219            = let bs = doubleToBytes (fromRational r)
220              in  map (\b -> ptext (sLit "\t.byte\t") <> pprImm (ImmInt b)) bs
221
222         ppr_item II16 _ = [ptext (sLit "\t.short\t") <> pprImm imm]
223
224         ppr_item II64 (CmmInt x _)  =
225                 [ptext (sLit "\t.long\t")
226                     <> int (fromIntegral 
227                         (fromIntegral (x `shiftR` 32) :: Word32)),
228                  ptext (sLit "\t.long\t")
229                     <> int (fromIntegral (fromIntegral x :: Word32))]
230
231         ppr_item _ _
232                 = panic "PPC.Ppr.pprDataItem: no match"
233
234
235 pprInstr :: Instr -> Doc
236
237 pprInstr (COMMENT _) = empty -- nuke 'em
238 {-
239 pprInstr (COMMENT s)
240    =  IF_ARCH_alpha( ((<>) (ptext (sLit "\t# ")) (ftext s))
241      ,IF_ARCH_sparc( ((<>) (ptext (sLit "# "))   (ftext s))
242      ,IF_ARCH_i386( ((<>) (ptext (sLit "# "))   (ftext s))
243      ,IF_ARCH_x86_64( ((<>) (ptext (sLit "# "))   (ftext s))
244      ,IF_ARCH_powerpc( IF_OS_linux(
245         ((<>) (ptext (sLit "# ")) (ftext s)),
246         ((<>) (ptext (sLit "; ")) (ftext s)))
247      ,)))))
248 -}
249 pprInstr (DELTA d)
250    = pprInstr (COMMENT (mkFastString ("\tdelta = " ++ show d)))
251
252 pprInstr (NEWBLOCK _)
253    = panic "PprMach.pprInstr: NEWBLOCK"
254
255 pprInstr (LDATA _ _)
256    = panic "PprMach.pprInstr: LDATA"
257
258
259 pprInstr (SPILL reg slot)
260    = hcat [
261         ptext (sLit "\tSPILL"),
262         char '\t',
263         pprReg reg,
264         comma,
265         ptext (sLit "SLOT") <> parens (int slot)]
266
267 pprInstr (RELOAD slot reg)
268    = hcat [
269         ptext (sLit "\tRELOAD"),
270         char '\t',
271         ptext (sLit "SLOT") <> parens (int slot),
272         comma,
273         pprReg reg]
274
275 pprInstr (LD sz reg addr) = hcat [
276         char '\t',
277         ptext (sLit "l"),
278         ptext (case sz of
279             II8  -> sLit "bz"
280             II16 -> sLit "hz"
281             II32 -> sLit "wz"
282             FF32 -> sLit "fs"
283             FF64 -> sLit "fd"
284             _    -> panic "PPC.Ppr.pprInstr: no match"
285             ),
286         case addr of AddrRegImm _ _ -> empty
287                      AddrRegReg _ _ -> char 'x',
288         char '\t',
289         pprReg reg,
290         ptext (sLit ", "),
291         pprAddr addr
292     ]
293 pprInstr (LA sz reg addr) = hcat [
294         char '\t',
295         ptext (sLit "l"),
296         ptext (case sz of
297             II8  -> sLit "ba"
298             II16 -> sLit "ha"
299             II32 -> sLit "wa"
300             FF32 -> sLit "fs"
301             FF64 -> sLit "fd"
302             _    -> panic "PPC.Ppr.pprInstr: no match"
303             ),
304         case addr of AddrRegImm _ _ -> empty
305                      AddrRegReg _ _ -> char 'x',
306         char '\t',
307         pprReg reg,
308         ptext (sLit ", "),
309         pprAddr addr
310     ]
311 pprInstr (ST sz reg addr) = hcat [
312         char '\t',
313         ptext (sLit "st"),
314         pprSize sz,
315         case addr of AddrRegImm _ _ -> empty
316                      AddrRegReg _ _ -> char 'x',
317         char '\t',
318         pprReg reg,
319         ptext (sLit ", "),
320         pprAddr addr
321     ]
322 pprInstr (STU sz reg addr) = hcat [
323         char '\t',
324         ptext (sLit "st"),
325         pprSize sz,
326         ptext (sLit "u\t"),
327         case addr of AddrRegImm _ _ -> empty
328                      AddrRegReg _ _ -> char 'x',
329         pprReg reg,
330         ptext (sLit ", "),
331         pprAddr addr
332     ]
333 pprInstr (LIS reg imm) = hcat [
334         char '\t',
335         ptext (sLit "lis"),
336         char '\t',
337         pprReg reg,
338         ptext (sLit ", "),
339         pprImm imm
340     ]
341 pprInstr (LI reg imm) = hcat [
342         char '\t',
343         ptext (sLit "li"),
344         char '\t',
345         pprReg reg,
346         ptext (sLit ", "),
347         pprImm imm
348     ]
349 pprInstr (MR reg1 reg2) 
350     | reg1 == reg2 = empty
351     | otherwise = hcat [
352         char '\t',
353         case regClass reg1 of
354             RcInteger -> ptext (sLit "mr")
355             _ -> ptext (sLit "fmr"),
356         char '\t',
357         pprReg reg1,
358         ptext (sLit ", "),
359         pprReg reg2
360     ]
361 pprInstr (CMP sz reg ri) = hcat [
362         char '\t',
363         op,
364         char '\t',
365         pprReg reg,
366         ptext (sLit ", "),
367         pprRI ri
368     ]
369     where
370         op = hcat [
371                 ptext (sLit "cmp"),
372                 pprSize sz,
373                 case ri of
374                     RIReg _ -> empty
375                     RIImm _ -> char 'i'
376             ]
377 pprInstr (CMPL sz reg ri) = hcat [
378         char '\t',
379         op,
380         char '\t',
381         pprReg reg,
382         ptext (sLit ", "),
383         pprRI ri
384     ]
385     where
386         op = hcat [
387                 ptext (sLit "cmpl"),
388                 pprSize sz,
389                 case ri of
390                     RIReg _ -> empty
391                     RIImm _ -> char 'i'
392             ]
393 pprInstr (BCC cond (BlockId id)) = hcat [
394         char '\t',
395         ptext (sLit "b"),
396         pprCond cond,
397         char '\t',
398         pprCLabel_asm lbl
399     ]
400     where lbl = mkAsmTempLabel id
401
402 pprInstr (BCCFAR cond (BlockId id)) = vcat [
403         hcat [
404             ptext (sLit "\tb"),
405             pprCond (condNegate cond),
406             ptext (sLit "\t$+8")
407         ],
408         hcat [
409             ptext (sLit "\tb\t"),
410             pprCLabel_asm lbl
411         ]
412     ]
413     where lbl = mkAsmTempLabel id
414
415 pprInstr (JMP lbl) = hcat [ -- an alias for b that takes a CLabel
416         char '\t',
417         ptext (sLit "b"),
418         char '\t',
419         pprCLabel_asm lbl
420     ]
421
422 pprInstr (MTCTR reg) = hcat [
423         char '\t',
424         ptext (sLit "mtctr"),
425         char '\t',
426         pprReg reg
427     ]
428 pprInstr (BCTR _) = hcat [
429         char '\t',
430         ptext (sLit "bctr")
431     ]
432 pprInstr (BL lbl _) = hcat [
433         ptext (sLit "\tbl\t"),
434         pprCLabel_asm lbl
435     ]
436 pprInstr (BCTRL _) = hcat [
437         char '\t',
438         ptext (sLit "bctrl")
439     ]
440 pprInstr (ADD reg1 reg2 ri) = pprLogic (sLit "add") reg1 reg2 ri
441 pprInstr (ADDIS reg1 reg2 imm) = hcat [
442         char '\t',
443         ptext (sLit "addis"),
444         char '\t',
445         pprReg reg1,
446         ptext (sLit ", "),
447         pprReg reg2,
448         ptext (sLit ", "),
449         pprImm imm
450     ]
451
452 pprInstr (ADDC reg1 reg2 reg3) = pprLogic (sLit "addc") reg1 reg2 (RIReg reg3)
453 pprInstr (ADDE reg1 reg2 reg3) = pprLogic (sLit "adde") reg1 reg2 (RIReg reg3)
454 pprInstr (SUBF reg1 reg2 reg3) = pprLogic (sLit "subf") reg1 reg2 (RIReg reg3)
455 pprInstr (MULLW reg1 reg2 ri@(RIReg _)) = pprLogic (sLit "mullw") reg1 reg2 ri
456 pprInstr (MULLW reg1 reg2 ri@(RIImm _)) = pprLogic (sLit "mull") reg1 reg2 ri
457 pprInstr (DIVW reg1 reg2 reg3) = pprLogic (sLit "divw") reg1 reg2 (RIReg reg3)
458 pprInstr (DIVWU reg1 reg2 reg3) = pprLogic (sLit "divwu") reg1 reg2 (RIReg reg3)
459
460 pprInstr (MULLW_MayOflo reg1 reg2 reg3) = vcat [
461          hcat [ ptext (sLit "\tmullwo\t"), pprReg reg1, ptext (sLit ", "),
462                                           pprReg reg2, ptext (sLit ", "),
463                                           pprReg reg3 ],
464          hcat [ ptext (sLit "\tmfxer\t"),  pprReg reg1 ],
465          hcat [ ptext (sLit "\trlwinm\t"), pprReg reg1, ptext (sLit ", "),
466                                           pprReg reg1, ptext (sLit ", "),
467                                           ptext (sLit "2, 31, 31") ]
468     ]
469
470         -- for some reason, "andi" doesn't exist.
471         -- we'll use "andi." instead.
472 pprInstr (AND reg1 reg2 (RIImm imm)) = hcat [
473         char '\t',
474         ptext (sLit "andi."),
475         char '\t',
476         pprReg reg1,
477         ptext (sLit ", "),
478         pprReg reg2,
479         ptext (sLit ", "),
480         pprImm imm
481     ]
482 pprInstr (AND reg1 reg2 ri) = pprLogic (sLit "and") reg1 reg2 ri
483
484 pprInstr (OR reg1 reg2 ri) = pprLogic (sLit "or") reg1 reg2 ri
485 pprInstr (XOR reg1 reg2 ri) = pprLogic (sLit "xor") reg1 reg2 ri
486
487 pprInstr (XORIS reg1 reg2 imm) = hcat [
488         char '\t',
489         ptext (sLit "xoris"),
490         char '\t',
491         pprReg reg1,
492         ptext (sLit ", "),
493         pprReg reg2,
494         ptext (sLit ", "),
495         pprImm imm
496     ]
497
498 pprInstr (EXTS sz reg1 reg2) = hcat [
499         char '\t',
500         ptext (sLit "exts"),
501         pprSize sz,
502         char '\t',
503         pprReg reg1,
504         ptext (sLit ", "),
505         pprReg reg2
506     ]
507
508 pprInstr (NEG reg1 reg2) = pprUnary (sLit "neg") reg1 reg2
509 pprInstr (NOT reg1 reg2) = pprUnary (sLit "not") reg1 reg2
510
511 pprInstr (SLW reg1 reg2 ri) = pprLogic (sLit "slw") reg1 reg2 (limitShiftRI ri)
512 pprInstr (SRW reg1 reg2 ri) = pprLogic (sLit "srw") reg1 reg2 (limitShiftRI ri)
513 pprInstr (SRAW reg1 reg2 ri) = pprLogic (sLit "sraw") reg1 reg2 (limitShiftRI ri)
514 pprInstr (RLWINM reg1 reg2 sh mb me) = hcat [
515         ptext (sLit "\trlwinm\t"),
516         pprReg reg1,
517         ptext (sLit ", "),
518         pprReg reg2,
519         ptext (sLit ", "),
520         int sh,
521         ptext (sLit ", "),
522         int mb,
523         ptext (sLit ", "),
524         int me
525     ]
526     
527 pprInstr (FADD sz reg1 reg2 reg3) = pprBinaryF (sLit "fadd") sz reg1 reg2 reg3
528 pprInstr (FSUB sz reg1 reg2 reg3) = pprBinaryF (sLit "fsub") sz reg1 reg2 reg3
529 pprInstr (FMUL sz reg1 reg2 reg3) = pprBinaryF (sLit "fmul") sz reg1 reg2 reg3
530 pprInstr (FDIV sz reg1 reg2 reg3) = pprBinaryF (sLit "fdiv") sz reg1 reg2 reg3
531 pprInstr (FNEG reg1 reg2) = pprUnary (sLit "fneg") reg1 reg2
532
533 pprInstr (FCMP reg1 reg2) = hcat [
534         char '\t',
535         ptext (sLit "fcmpu\tcr0, "),
536             -- Note: we're using fcmpu, not fcmpo
537             -- The difference is with fcmpo, compare with NaN is an invalid operation.
538             -- We don't handle invalid fp ops, so we don't care
539         pprReg reg1,
540         ptext (sLit ", "),
541         pprReg reg2
542     ]
543
544 pprInstr (FCTIWZ reg1 reg2) = pprUnary (sLit "fctiwz") reg1 reg2
545 pprInstr (FRSP reg1 reg2) = pprUnary (sLit "frsp") reg1 reg2
546
547 pprInstr (CRNOR dst src1 src2) = hcat [
548         ptext (sLit "\tcrnor\t"),
549         int dst,
550         ptext (sLit ", "),
551         int src1,
552         ptext (sLit ", "),
553         int src2
554     ]
555
556 pprInstr (MFCR reg) = hcat [
557         char '\t',
558         ptext (sLit "mfcr"),
559         char '\t',
560         pprReg reg
561     ]
562
563 pprInstr (MFLR reg) = hcat [
564         char '\t',
565         ptext (sLit "mflr"),
566         char '\t',
567         pprReg reg
568     ]
569
570 pprInstr (FETCHPC reg) = vcat [
571         ptext (sLit "\tbcl\t20,31,1f"),
572         hcat [ ptext (sLit "1:\tmflr\t"), pprReg reg ]
573     ]
574
575 pprInstr LWSYNC = ptext (sLit "\tlwsync")
576
577 -- pprInstr _ = panic "pprInstr (ppc)"
578
579
580 pprLogic :: LitString -> Reg -> Reg -> RI -> Doc
581 pprLogic op reg1 reg2 ri = hcat [
582         char '\t',
583         ptext op,
584         case ri of
585             RIReg _ -> empty
586             RIImm _ -> char 'i',
587         char '\t',
588         pprReg reg1,
589         ptext (sLit ", "),
590         pprReg reg2,
591         ptext (sLit ", "),
592         pprRI ri
593     ]
594
595
596 pprUnary :: LitString -> Reg -> Reg -> Doc    
597 pprUnary op reg1 reg2 = hcat [
598         char '\t',
599         ptext op,
600         char '\t',
601         pprReg reg1,
602         ptext (sLit ", "),
603         pprReg reg2
604     ]
605     
606     
607 pprBinaryF :: LitString -> Size -> Reg -> Reg -> Reg -> Doc
608 pprBinaryF op sz reg1 reg2 reg3 = hcat [
609         char '\t',
610         ptext op,
611         pprFSize sz,
612         char '\t',
613         pprReg reg1,
614         ptext (sLit ", "),
615         pprReg reg2,
616         ptext (sLit ", "),
617         pprReg reg3
618     ]
619     
620 pprRI :: RI -> Doc
621 pprRI (RIReg r) = pprReg r
622 pprRI (RIImm r) = pprImm r
623
624
625 pprFSize :: Size -> Doc
626 pprFSize FF64   = empty
627 pprFSize FF32   = char 's'
628 pprFSize _      = panic "PPC.Ppr.pprFSize: no match"
629
630     -- limit immediate argument for shift instruction to range 0..32
631     -- (yes, the maximum is really 32, not 31)
632 limitShiftRI :: RI -> RI
633 limitShiftRI (RIImm (ImmInt i)) | i > 32 || i < 0 = RIImm (ImmInt 32)
634 limitShiftRI x = x
635