SPARC NCG: Split up into chunks, and fix warnings.
[ghc-hetmet.git] / compiler / nativeGen / SPARC / CodeGen / Gen32.hs
1
2 -- | Evaluation of 32 bit values.
3 module SPARC.CodeGen.Gen32 (
4         getSomeReg,
5         getRegister
6 )
7
8 where
9
10 import SPARC.CodeGen.CondCode
11 import SPARC.CodeGen.Amode
12 import SPARC.CodeGen.Gen64
13 import SPARC.CodeGen.Base
14 import SPARC.Stack
15 import SPARC.Instr
16 import SPARC.Cond
17 import SPARC.AddrMode
18 import SPARC.Imm
19 import SPARC.Regs
20 import SPARC.Base
21 import NCGMonad
22 import Size
23 import Reg
24
25 import Cmm
26 import BlockId
27
28 import OrdList
29 import Outputable
30
31 -- | The dual to getAnyReg: compute an expression into a register, but
32 --      we don't mind which one it is.
33 getSomeReg :: CmmExpr -> NatM (Reg, InstrBlock)
34 getSomeReg expr = do
35   r <- getRegister expr
36   case r of
37     Any rep code -> do
38         tmp <- getNewRegNat rep
39         return (tmp, code tmp)
40     Fixed _ reg code -> 
41         return (reg, code)
42
43
44
45 -- | Make code to evaluate a 32 bit expression.
46 --
47 getRegister :: CmmExpr -> NatM Register
48
49 getRegister (CmmReg reg) 
50   = return (Fixed (cmmTypeSize (cmmRegType reg)) 
51                   (getRegisterReg reg) nilOL)
52
53 getRegister tree@(CmmRegOff _ _) 
54   = getRegister (mangleIndexTree tree)
55
56 getRegister (CmmMachOp (MO_UU_Conv W64 W32)
57              [CmmMachOp (MO_U_Shr W64) [x,CmmLit (CmmInt 32 _)]]) = do
58   ChildCode64 code rlo <- iselExpr64 x
59   return $ Fixed II32 (getHiVRegFromLo rlo) code
60
61 getRegister (CmmMachOp (MO_SS_Conv W64 W32)
62              [CmmMachOp (MO_U_Shr W64) [x,CmmLit (CmmInt 32 _)]]) = do
63   ChildCode64 code rlo <- iselExpr64 x
64   return $ Fixed II32 (getHiVRegFromLo rlo) code
65
66 getRegister (CmmMachOp (MO_UU_Conv W64 W32) [x]) = do
67   ChildCode64 code rlo <- iselExpr64 x
68   return $ Fixed II32 rlo code
69
70 getRegister (CmmMachOp (MO_SS_Conv W64 W32) [x]) = do
71   ChildCode64 code rlo <- iselExpr64 x
72   return $ Fixed II32 rlo code       
73
74
75 -- Load a literal float into a float register.
76 --      The actual literal is stored in a new data area, and we load it 
77 --      at runtime.
78 getRegister (CmmLit (CmmFloat f W32)) = do
79
80     -- a label for the new data area
81     lbl <- getNewLabelNat
82     tmp <- getNewRegNat II32
83
84     let code dst = toOL [
85             -- the data area         
86             LDATA ReadOnlyData
87                         [CmmDataLabel lbl,
88                          CmmStaticLit (CmmFloat f W32)],
89
90             -- load the literal
91             SETHI (HI (ImmCLbl lbl)) tmp,
92             LD II32 (AddrRegImm tmp (LO (ImmCLbl lbl))) dst] 
93
94     return (Any FF32 code)
95
96 getRegister (CmmLit (CmmFloat d W64)) = do
97     lbl <- getNewLabelNat
98     tmp <- getNewRegNat II32
99     let code dst = toOL [
100             LDATA ReadOnlyData
101                         [CmmDataLabel lbl,
102                          CmmStaticLit (CmmFloat d W64)],
103             SETHI (HI (ImmCLbl lbl)) tmp,
104             LD II64 (AddrRegImm tmp (LO (ImmCLbl lbl))) dst] 
105     return (Any FF64 code)
106
107 getRegister (CmmMachOp mop [x]) -- unary MachOps
108   = case mop of
109       MO_F_Neg W32     -> trivialUFCode FF32 (FNEG FF32) x
110       MO_F_Neg W64     -> trivialUFCode FF64 (FNEG FF64) x
111
112       MO_S_Neg rep     -> trivialUCode (intSize rep) (SUB False False g0) x
113       MO_Not rep       -> trivialUCode (intSize rep) (XNOR False g0) x
114
115       MO_FF_Conv W64 W32-> coerceDbl2Flt x
116       MO_FF_Conv W32 W64-> coerceFlt2Dbl x
117
118       MO_FS_Conv from to -> coerceFP2Int from to x
119       MO_SF_Conv from to -> coerceInt2FP from to x
120
121       -- Conversions which are a nop on sparc
122       MO_UU_Conv from to
123         | from == to    -> conversionNop (intSize to)  x
124       MO_UU_Conv W32 W8 -> trivialCode W8 (AND False) x (CmmLit (CmmInt 255 W8))
125       MO_UU_Conv W32 to -> conversionNop (intSize to) x
126       MO_SS_Conv W32 to -> conversionNop (intSize to) x
127
128       MO_UU_Conv W8  to@W32  -> conversionNop (intSize to)  x
129       MO_UU_Conv W16 to@W32  -> conversionNop (intSize to)  x
130       MO_UU_Conv W8  to@W16  -> conversionNop (intSize to)  x
131
132       -- sign extension
133       MO_SS_Conv W8  W32  -> integerExtend W8  W32 x
134       MO_SS_Conv W16 W32  -> integerExtend W16 W32 x
135       MO_SS_Conv W8  W16  -> integerExtend W8  W16 x
136
137       _                   -> panic ("Unknown unary mach op: " ++ show mop)
138
139
140 getRegister (CmmMachOp mop [x, y]) -- dyadic PrimOps
141   = case mop of
142       MO_Eq _           -> condIntReg EQQ x y
143       MO_Ne _           -> condIntReg NE x y
144
145       MO_S_Gt _         -> condIntReg GTT x y
146       MO_S_Ge _         -> condIntReg GE x y
147       MO_S_Lt _         -> condIntReg LTT x y
148       MO_S_Le _         -> condIntReg LE x y
149               
150       MO_U_Gt W32       -> condIntReg GTT x y
151       MO_U_Ge W32       -> condIntReg GE x y
152       MO_U_Lt W32       -> condIntReg LTT x y
153       MO_U_Le W32       -> condIntReg LE x y
154
155       MO_U_Gt W16       -> condIntReg GU  x y
156       MO_U_Ge W16       -> condIntReg GEU x y
157       MO_U_Lt W16       -> condIntReg LU  x y
158       MO_U_Le W16       -> condIntReg LEU x y
159
160       MO_Add W32        -> trivialCode W32 (ADD False False) x y
161       MO_Sub W32        -> trivialCode W32 (SUB False False) x y
162
163       MO_S_MulMayOflo rep -> imulMayOflo rep x y
164
165       MO_S_Quot W32     -> idiv True  False x y
166       MO_U_Quot W32     -> idiv False False x y
167        
168       MO_S_Rem  W32     -> irem True  x y
169       MO_U_Rem  W32     -> irem False x y
170        
171       MO_F_Eq _         -> condFltReg EQQ x y
172       MO_F_Ne _         -> condFltReg NE x y
173
174       MO_F_Gt _         -> condFltReg GTT x y
175       MO_F_Ge _         -> condFltReg GE x y 
176       MO_F_Lt _         -> condFltReg LTT x y
177       MO_F_Le _         -> condFltReg LE x y
178
179       MO_F_Add  w       -> trivialFCode w FADD x y
180       MO_F_Sub  w       -> trivialFCode w FSUB x y
181       MO_F_Mul  w       -> trivialFCode w FMUL x y
182       MO_F_Quot w       -> trivialFCode w FDIV x y
183
184       MO_And rep        -> trivialCode rep (AND False) x y
185       MO_Or  rep        -> trivialCode rep (OR  False) x y
186       MO_Xor rep        -> trivialCode rep (XOR False) x y
187
188       MO_Mul rep        -> trivialCode rep (SMUL False) x y
189
190       MO_Shl rep        -> trivialCode rep SLL  x y
191       MO_U_Shr rep      -> trivialCode rep SRL x y
192       MO_S_Shr rep      -> trivialCode rep SRA x y
193
194       _                 -> pprPanic "getRegister(sparc) - binary CmmMachOp (1)" (pprMachOp mop)
195   where
196
197
198 getRegister (CmmLoad mem pk) = do
199     Amode src code <- getAmode mem
200     let
201         code__2 dst     = code `snocOL` LD (cmmTypeSize pk) src dst
202     return (Any (cmmTypeSize pk) code__2)
203
204 getRegister (CmmLit (CmmInt i _))
205   | fits13Bits i
206   = let
207         src = ImmInt (fromInteger i)
208         code dst = unitOL (OR False g0 (RIImm src) dst)
209     in
210         return (Any II32 code)
211
212 getRegister (CmmLit lit)
213   = let imm = litToImm lit
214         code dst = toOL [
215             SETHI (HI imm) dst,
216             OR False dst (RIImm (LO imm)) dst]
217     in return (Any II32 code)
218
219
220 getRegister _
221         = panic "SPARC.CodeGen.Gen32.getRegister: no match"
222
223
224 -- | sign extend and widen
225 integerExtend 
226         :: Width                -- ^ width of source expression
227         -> Width                -- ^ width of result
228         -> CmmExpr              -- ^ source expression
229         -> NatM Register        
230
231 integerExtend from to expr
232  = do   -- load the expr into some register
233         (reg, e_code)   <- getSomeReg expr
234         tmp             <- getNewRegNat II32
235         let bitCount
236                 = case (from, to) of
237                         (W8,  W32)      -> 24
238                         (W16, W32)      -> 16
239                         (W8,  W16)      -> 24
240                         _               -> panic "SPARC.CodeGen.Gen32: no match"
241         let code dst
242                 = e_code        
243
244                 -- local shift word left to load the sign bit
245                 `snocOL`  SLL reg (RIImm (ImmInt bitCount)) tmp
246                         
247                 -- arithmetic shift right to sign extend
248                 `snocOL`  SRA tmp (RIImm (ImmInt bitCount)) dst
249                         
250         return (Any (intSize to) code)
251                                 
252
253 conversionNop
254         :: Size -> CmmExpr -> NatM Register
255 conversionNop new_rep expr
256  = do   e_code <- getRegister expr
257         return (setSizeOfRegister e_code new_rep)
258
259
260
261 -- | Generate an integer division instruction.
262 idiv :: Bool -> Bool -> CmmExpr -> CmmExpr -> NatM Register
263         
264 -- For unsigned division with a 32 bit numerator, 
265 --              we can just clear the Y register.
266 idiv False cc x y 
267  = do
268         (a_reg, a_code)         <- getSomeReg x
269         (b_reg, b_code)         <- getSomeReg y
270         
271         let code dst
272                 =       a_code 
273                 `appOL` b_code  
274                 `appOL` toOL
275                         [ WRY  g0 g0
276                         , UDIV cc a_reg (RIReg b_reg) dst]
277                         
278         return (Any II32 code)
279         
280
281 -- For _signed_ division with a 32 bit numerator,
282 --              we have to sign extend the numerator into the Y register.
283 idiv True cc x y 
284  = do
285         (a_reg, a_code)         <- getSomeReg x
286         (b_reg, b_code)         <- getSomeReg y
287         
288         tmp                     <- getNewRegNat II32
289         
290         let code dst
291                 =       a_code 
292                 `appOL` b_code  
293                 `appOL` toOL
294                         [ SRA  a_reg (RIImm (ImmInt 16)) tmp            -- sign extend
295                         , SRA  tmp   (RIImm (ImmInt 16)) tmp
296
297                         , WRY  tmp g0                           
298                         , SDIV cc a_reg (RIReg b_reg) dst]
299                         
300         return (Any II32 code)
301
302
303 -- | Do an integer remainder.
304 --
305 --       NOTE:  The SPARC v8 architecture manual says that integer division
306 --              instructions _may_ generate a remainder, depending on the implementation.
307 --              If so it is _recommended_ that the remainder is placed in the Y register.
308 --
309 --          The UltraSparc 2007 manual says Y is _undefined_ after division.
310 --
311 --              The SPARC T2 doesn't store the remainder, not sure about the others. 
312 --              It's probably best not to worry about it, and just generate our own
313 --              remainders. 
314 --
315 irem :: Bool -> CmmExpr -> CmmExpr -> NatM Register
316
317 -- For unsigned operands: 
318 --              Division is between a 64 bit numerator and a 32 bit denominator, 
319 --              so we still have to clear the Y register.
320 irem False x y 
321  = do
322         (a_reg, a_code) <- getSomeReg x
323         (b_reg, b_code) <- getSomeReg y
324
325         tmp_reg         <- getNewRegNat II32
326
327         let code dst
328                 =       a_code
329                 `appOL` b_code
330                 `appOL` toOL
331                         [ WRY   g0 g0
332                         , UDIV  False         a_reg (RIReg b_reg) tmp_reg
333                         , UMUL  False       tmp_reg (RIReg b_reg) tmp_reg
334                         , SUB   False False   a_reg (RIReg tmp_reg) dst]
335     
336         return  (Any II32 code)
337
338     
339
340 -- For signed operands:
341 --              Make sure to sign extend into the Y register, or the remainder
342 --              will have the wrong sign when the numerator is negative.
343 --
344 --      TODO:   When sign extending, GCC only shifts the a_reg right by 17 bits,
345 --              not the full 32. Not sure why this is, something to do with overflow?
346 --              If anyone cares enough about the speed of signed remainder they
347 --              can work it out themselves (then tell me). -- BL 2009/01/20
348 irem True x y 
349  = do
350         (a_reg, a_code) <- getSomeReg x
351         (b_reg, b_code) <- getSomeReg y
352         
353         tmp1_reg        <- getNewRegNat II32
354         tmp2_reg        <- getNewRegNat II32
355                 
356         let code dst
357                 =       a_code
358                 `appOL` b_code
359                 `appOL` toOL
360                         [ SRA   a_reg      (RIImm (ImmInt 16)) tmp1_reg -- sign extend
361                         , SRA   tmp1_reg   (RIImm (ImmInt 16)) tmp1_reg -- sign extend
362                         , WRY   tmp1_reg g0
363
364                         , SDIV  False          a_reg (RIReg b_reg)    tmp2_reg  
365                         , SMUL  False       tmp2_reg (RIReg b_reg)    tmp2_reg
366                         , SUB   False False    a_reg (RIReg tmp2_reg) dst]
367                         
368         return (Any II32 code)
369    
370
371 imulMayOflo :: Width -> CmmExpr -> CmmExpr -> NatM Register
372 imulMayOflo rep a b 
373  = do
374         (a_reg, a_code) <- getSomeReg a
375         (b_reg, b_code) <- getSomeReg b
376         res_lo <- getNewRegNat II32
377         res_hi <- getNewRegNat II32
378
379         let shift_amt  = case rep of
380                           W32 -> 31
381                           W64 -> 63
382                           _ -> panic "shift_amt"
383         
384         let code dst = a_code `appOL` b_code `appOL`
385                        toOL [
386                            SMUL False a_reg (RIReg b_reg) res_lo,
387                            RDY res_hi,
388                            SRA res_lo (RIImm (ImmInt shift_amt)) res_lo,
389                            SUB False False res_lo (RIReg res_hi) dst
390                         ]
391         return (Any II32 code)
392
393
394 -- -----------------------------------------------------------------------------
395 -- 'trivial*Code': deal with trivial instructions
396
397 -- Trivial (dyadic: 'trivialCode', floating-point: 'trivialFCode',
398 -- unary: 'trivialUCode', unary fl-pt:'trivialUFCode') instructions.
399 -- Only look for constants on the right hand side, because that's
400 -- where the generic optimizer will have put them.
401
402 -- Similarly, for unary instructions, we don't have to worry about
403 -- matching an StInt as the argument, because genericOpt will already
404 -- have handled the constant-folding.
405
406 trivialCode
407         :: Width
408         -> (Reg -> RI -> Reg -> Instr)
409         -> CmmExpr
410         -> CmmExpr
411         -> NatM Register
412         
413 trivialCode _ instr x (CmmLit (CmmInt y _))
414   | fits13Bits y
415   = do
416       (src1, code) <- getSomeReg x
417       let
418         src2 = ImmInt (fromInteger y)
419         code__2 dst = code `snocOL` instr src1 (RIImm src2) dst
420       return (Any II32 code__2)
421
422
423 trivialCode _ instr x y = do
424     (src1, code1) <- getSomeReg x
425     (src2, code2) <- getSomeReg y
426     let
427         code__2 dst = code1 `appOL` code2 `snocOL`
428                       instr src1 (RIReg src2) dst
429     return (Any II32 code__2)
430
431
432 trivialFCode 
433         :: Width
434         -> (Size -> Reg -> Reg -> Reg -> Instr)
435         -> CmmExpr
436         -> CmmExpr
437         -> NatM Register
438
439 trivialFCode pk instr x y = do
440     (src1, code1) <- getSomeReg x
441     (src2, code2) <- getSomeReg y
442     tmp <- getNewRegNat FF64
443     let
444         promote x = FxTOy FF32 FF64 x tmp
445
446         pk1   = cmmExprType x
447         pk2   = cmmExprType y
448
449         code__2 dst =
450                 if pk1 `cmmEqType` pk2 then
451                     code1 `appOL` code2 `snocOL`
452                     instr (floatSize pk) src1 src2 dst
453                 else if typeWidth pk1 == W32 then
454                     code1 `snocOL` promote src1 `appOL` code2 `snocOL`
455                     instr FF64 tmp src2 dst
456                 else
457                     code1 `appOL` code2 `snocOL` promote src2 `snocOL`
458                     instr FF64 src1 tmp dst
459     return (Any (cmmTypeSize $ if pk1 `cmmEqType` pk2 then pk1 else cmmFloat W64) 
460                 code__2)
461
462
463
464 trivialUCode
465         :: Size
466         -> (RI -> Reg -> Instr)
467         -> CmmExpr
468         -> NatM Register
469         
470 trivialUCode size instr x = do
471     (src, code) <- getSomeReg x
472     let
473         code__2 dst = code `snocOL` instr (RIReg src) dst
474     return (Any size code__2)
475
476
477 trivialUFCode 
478         :: Size
479         -> (Reg -> Reg -> Instr)
480         -> CmmExpr
481         -> NatM Register 
482         
483 trivialUFCode pk instr x = do
484     (src, code) <- getSomeReg x
485     let
486         code__2 dst = code `snocOL` instr src dst
487     return (Any pk code__2)
488
489
490
491
492 -- Coercions -------------------------------------------------------------------
493
494 -- | Coerce a integer value to floating point
495 coerceInt2FP :: Width -> Width -> CmmExpr -> NatM Register
496 coerceInt2FP width1 width2 x = do
497     (src, code) <- getSomeReg x
498     let
499         code__2 dst = code `appOL` toOL [
500             ST (intSize width1) src (spRel (-2)),
501             LD (intSize width1) (spRel (-2)) dst,
502             FxTOy (intSize width1) (floatSize width2) dst dst]
503     return (Any (floatSize $ width2) code__2)
504
505
506
507 -- | Coerce a floating point value to integer
508 --
509 --   NOTE: On sparc v9 there are no instructions to move a value from an
510 --         FP register directly to an int register, so we have to use a load/store.
511 --
512 coerceFP2Int :: Width -> Width -> CmmExpr -> NatM Register
513 coerceFP2Int width1 width2 x 
514  = do   let fsize1      = floatSize width1
515             fsize2      = floatSize width2
516         
517             isize2      = intSize   width2
518
519         (fsrc, code)    <- getSomeReg x
520         fdst            <- getNewRegNat fsize2
521     
522         let code2 dst   
523                 =       code
524                 `appOL` toOL
525                         -- convert float to int format, leaving it in a float reg.
526                         [ FxTOy fsize1 isize2 fsrc fdst
527
528                         -- store the int into mem, then load it back to move
529                         --      it into an actual int reg.
530                         , ST    fsize2 fdst (spRel (-2))
531                         , LD    isize2 (spRel (-2)) dst]
532
533         return (Any isize2 code2)
534
535
536 -- | Coerce a double precision floating point value to single precision.
537 coerceDbl2Flt :: CmmExpr -> NatM Register
538 coerceDbl2Flt x = do
539     (src, code) <- getSomeReg x
540     return (Any FF32 (\dst -> code `snocOL` FxTOy FF64 FF32 src dst)) 
541
542
543 -- | Coerce a single precision floating point value to double precision
544 coerceFlt2Dbl :: CmmExpr -> NatM Register
545 coerceFlt2Dbl x = do
546     (src, code) <- getSomeReg x
547     return (Any FF64 (\dst -> code `snocOL` FxTOy FF32 FF64 src dst))
548
549
550
551
552 -- Condition Codes -------------------------------------------------------------
553 --
554 -- Evaluate a comparision, and get the result into a register.
555 -- 
556 -- Do not fill the delay slots here. you will confuse the register allocator.
557 --
558 condIntReg :: Cond -> CmmExpr -> CmmExpr -> NatM Register
559 condIntReg EQQ x (CmmLit (CmmInt 0 _)) = do
560     (src, code) <- getSomeReg x
561     let
562         code__2 dst = code `appOL` toOL [
563             SUB False True g0 (RIReg src) g0,
564             SUB True False g0 (RIImm (ImmInt (-1))) dst]
565     return (Any II32 code__2)
566
567 condIntReg EQQ x y = do
568     (src1, code1) <- getSomeReg x
569     (src2, code2) <- getSomeReg y
570     let
571         code__2 dst = code1 `appOL` code2 `appOL` toOL [
572             XOR False src1 (RIReg src2) dst,
573             SUB False True g0 (RIReg dst) g0,
574             SUB True False g0 (RIImm (ImmInt (-1))) dst]
575     return (Any II32 code__2)
576
577 condIntReg NE x (CmmLit (CmmInt 0 _)) = do
578     (src, code) <- getSomeReg x
579     let
580         code__2 dst = code `appOL` toOL [
581             SUB False True g0 (RIReg src) g0,
582             ADD True False g0 (RIImm (ImmInt 0)) dst]
583     return (Any II32 code__2)
584
585 condIntReg NE x y = do
586     (src1, code1) <- getSomeReg x
587     (src2, code2) <- getSomeReg y
588     let
589         code__2 dst = code1 `appOL` code2 `appOL` toOL [
590             XOR False src1 (RIReg src2) dst,
591             SUB False True g0 (RIReg dst) g0,
592             ADD True False g0 (RIImm (ImmInt 0)) dst]
593     return (Any II32 code__2)
594
595 condIntReg cond x y = do
596     bid1@(BlockId _) <- getBlockIdNat
597     bid2@(BlockId _) <- getBlockIdNat
598     CondCode _ cond cond_code <- condIntCode cond x y
599     let
600         code__2 dst = cond_code `appOL` toOL [
601             BI cond False bid1, NOP,
602             OR False g0 (RIImm (ImmInt 0)) dst,
603             BI ALWAYS False bid2, NOP,
604             NEWBLOCK bid1,
605             OR False g0 (RIImm (ImmInt 1)) dst,
606             NEWBLOCK bid2]
607     return (Any II32 code__2)
608
609
610 condFltReg :: Cond -> CmmExpr -> CmmExpr -> NatM Register
611 condFltReg cond x y = do
612     bid1@(BlockId _) <- getBlockIdNat
613     bid2@(BlockId _) <- getBlockIdNat
614
615     CondCode _ cond cond_code <- condFltCode cond x y
616     let
617         code__2 dst = cond_code `appOL` toOL [ 
618             NOP,
619             BF cond False bid1, NOP,
620             OR False g0 (RIImm (ImmInt 0)) dst,
621             BI ALWAYS False bid2, NOP,
622             NEWBLOCK bid1,
623             OR False g0 (RIImm (ImmInt 1)) dst,
624             NEWBLOCK bid2]
625     return (Any II32 code__2)