2 -- | Evaluation of 32 bit values.
3 module SPARC.CodeGen.Gen32 (
10 import SPARC.CodeGen.CondCode
11 import SPARC.CodeGen.Amode
12 import SPARC.CodeGen.Gen64
13 import SPARC.CodeGen.Base
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)
38 tmp <- getNewRegNat rep
39 return (tmp, code tmp)
45 -- | Make code to evaluate a 32 bit expression.
47 getRegister :: CmmExpr -> NatM Register
49 getRegister (CmmReg reg)
50 = return (Fixed (cmmTypeSize (cmmRegType reg))
51 (getRegisterReg reg) nilOL)
53 getRegister tree@(CmmRegOff _ _)
54 = getRegister (mangleIndexTree tree)
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
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
66 getRegister (CmmMachOp (MO_UU_Conv W64 W32) [x]) = do
67 ChildCode64 code rlo <- iselExpr64 x
68 return $ Fixed II32 rlo code
70 getRegister (CmmMachOp (MO_SS_Conv W64 W32) [x]) = do
71 ChildCode64 code rlo <- iselExpr64 x
72 return $ Fixed II32 rlo code
75 -- Load a literal float into a float register.
76 -- The actual literal is stored in a new data area, and we load it
78 getRegister (CmmLit (CmmFloat f W32)) = do
80 -- a label for the new data area
82 tmp <- getNewRegNat II32
88 CmmStaticLit (CmmFloat f W32)],
91 SETHI (HI (ImmCLbl lbl)) tmp,
92 LD II32 (AddrRegImm tmp (LO (ImmCLbl lbl))) dst]
94 return (Any FF32 code)
96 getRegister (CmmLit (CmmFloat d W64)) = do
98 tmp <- getNewRegNat II32
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)
107 getRegister (CmmMachOp mop [x]) -- unary MachOps
109 MO_F_Neg W32 -> trivialUFCode FF32 (FNEG FF32) x
110 MO_F_Neg W64 -> trivialUFCode FF64 (FNEG FF64) x
112 MO_S_Neg rep -> trivialUCode (intSize rep) (SUB False False g0) x
113 MO_Not rep -> trivialUCode (intSize rep) (XNOR False g0) x
115 MO_FF_Conv W64 W32-> coerceDbl2Flt x
116 MO_FF_Conv W32 W64-> coerceFlt2Dbl x
118 MO_FS_Conv from to -> coerceFP2Int from to x
119 MO_SF_Conv from to -> coerceInt2FP from to x
121 -- Conversions which are a nop on sparc
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
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
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
137 _ -> panic ("Unknown unary mach op: " ++ show mop)
140 getRegister (CmmMachOp mop [x, y]) -- dyadic PrimOps
142 MO_Eq _ -> condIntReg EQQ x y
143 MO_Ne _ -> condIntReg NE x y
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
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
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
160 MO_Add W32 -> trivialCode W32 (ADD False False) x y
161 MO_Sub W32 -> trivialCode W32 (SUB False False) x y
163 MO_S_MulMayOflo rep -> imulMayOflo rep x y
165 MO_S_Quot W32 -> idiv True False x y
166 MO_U_Quot W32 -> idiv False False x y
168 MO_S_Rem W32 -> irem True x y
169 MO_U_Rem W32 -> irem False x y
171 MO_F_Eq _ -> condFltReg EQQ x y
172 MO_F_Ne _ -> condFltReg NE x y
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
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
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
188 MO_Mul rep -> trivialCode rep (SMUL False) x y
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
194 _ -> pprPanic "getRegister(sparc) - binary CmmMachOp (1)" (pprMachOp mop)
198 getRegister (CmmLoad mem pk) = do
199 Amode src code <- getAmode mem
201 code__2 dst = code `snocOL` LD (cmmTypeSize pk) src dst
202 return (Any (cmmTypeSize pk) code__2)
204 getRegister (CmmLit (CmmInt i _))
207 src = ImmInt (fromInteger i)
208 code dst = unitOL (OR False g0 (RIImm src) dst)
210 return (Any II32 code)
212 getRegister (CmmLit lit)
213 = let imm = litToImm lit
216 OR False dst (RIImm (LO imm)) dst]
217 in return (Any II32 code)
221 = panic "SPARC.CodeGen.Gen32.getRegister: no match"
224 -- | sign extend and widen
226 :: Width -- ^ width of source expression
227 -> Width -- ^ width of result
228 -> CmmExpr -- ^ source expression
231 integerExtend from to expr
232 = do -- load the expr into some register
233 (reg, e_code) <- getSomeReg expr
234 tmp <- getNewRegNat II32
240 _ -> panic "SPARC.CodeGen.Gen32: no match"
244 -- local shift word left to load the sign bit
245 `snocOL` SLL reg (RIImm (ImmInt bitCount)) tmp
247 -- arithmetic shift right to sign extend
248 `snocOL` SRA tmp (RIImm (ImmInt bitCount)) dst
250 return (Any (intSize to) code)
254 :: Size -> CmmExpr -> NatM Register
255 conversionNop new_rep expr
256 = do e_code <- getRegister expr
257 return (setSizeOfRegister e_code new_rep)
261 -- | Generate an integer division instruction.
262 idiv :: Bool -> Bool -> CmmExpr -> CmmExpr -> NatM Register
264 -- For unsigned division with a 32 bit numerator,
265 -- we can just clear the Y register.
268 (a_reg, a_code) <- getSomeReg x
269 (b_reg, b_code) <- getSomeReg y
276 , UDIV cc a_reg (RIReg b_reg) dst]
278 return (Any II32 code)
281 -- For _signed_ division with a 32 bit numerator,
282 -- we have to sign extend the numerator into the Y register.
285 (a_reg, a_code) <- getSomeReg x
286 (b_reg, b_code) <- getSomeReg y
288 tmp <- getNewRegNat II32
294 [ SRA a_reg (RIImm (ImmInt 16)) tmp -- sign extend
295 , SRA tmp (RIImm (ImmInt 16)) tmp
298 , SDIV cc a_reg (RIReg b_reg) dst]
300 return (Any II32 code)
303 -- | Do an integer remainder.
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.
309 -- The UltraSparc 2007 manual says Y is _undefined_ after division.
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
315 irem :: Bool -> CmmExpr -> CmmExpr -> NatM Register
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.
322 (a_reg, a_code) <- getSomeReg x
323 (b_reg, b_code) <- getSomeReg y
325 tmp_reg <- getNewRegNat II32
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]
336 return (Any II32 code)
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.
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
350 (a_reg, a_code) <- getSomeReg x
351 (b_reg, b_code) <- getSomeReg y
353 tmp1_reg <- getNewRegNat II32
354 tmp2_reg <- getNewRegNat II32
360 [ SRA a_reg (RIImm (ImmInt 16)) tmp1_reg -- sign extend
361 , SRA tmp1_reg (RIImm (ImmInt 16)) tmp1_reg -- sign extend
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]
368 return (Any II32 code)
371 imulMayOflo :: Width -> CmmExpr -> CmmExpr -> NatM Register
374 (a_reg, a_code) <- getSomeReg a
375 (b_reg, b_code) <- getSomeReg b
376 res_lo <- getNewRegNat II32
377 res_hi <- getNewRegNat II32
379 let shift_amt = case rep of
382 _ -> panic "shift_amt"
384 let code dst = a_code `appOL` b_code `appOL`
386 SMUL False a_reg (RIReg b_reg) res_lo,
388 SRA res_lo (RIImm (ImmInt shift_amt)) res_lo,
389 SUB False False res_lo (RIReg res_hi) dst
391 return (Any II32 code)
394 -- -----------------------------------------------------------------------------
395 -- 'trivial*Code': deal with trivial instructions
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.
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.
408 -> (Reg -> RI -> Reg -> Instr)
413 trivialCode _ instr x (CmmLit (CmmInt y _))
416 (src1, code) <- getSomeReg x
418 src2 = ImmInt (fromInteger y)
419 code__2 dst = code `snocOL` instr src1 (RIImm src2) dst
420 return (Any II32 code__2)
423 trivialCode _ instr x y = do
424 (src1, code1) <- getSomeReg x
425 (src2, code2) <- getSomeReg y
427 code__2 dst = code1 `appOL` code2 `snocOL`
428 instr src1 (RIReg src2) dst
429 return (Any II32 code__2)
434 -> (Size -> Reg -> Reg -> Reg -> Instr)
439 trivialFCode pk instr x y = do
440 (src1, code1) <- getSomeReg x
441 (src2, code2) <- getSomeReg y
442 tmp <- getNewRegNat FF64
444 promote x = FxTOy FF32 FF64 x tmp
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
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)
466 -> (RI -> Reg -> Instr)
470 trivialUCode size instr x = do
471 (src, code) <- getSomeReg x
473 code__2 dst = code `snocOL` instr (RIReg src) dst
474 return (Any size code__2)
479 -> (Reg -> Reg -> Instr)
483 trivialUFCode pk instr x = do
484 (src, code) <- getSomeReg x
486 code__2 dst = code `snocOL` instr src dst
487 return (Any pk code__2)
492 -- Coercions -------------------------------------------------------------------
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
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)
507 -- | Coerce a floating point value to integer
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.
512 coerceFP2Int :: Width -> Width -> CmmExpr -> NatM Register
513 coerceFP2Int width1 width2 x
514 = do let fsize1 = floatSize width1
515 fsize2 = floatSize width2
517 isize2 = intSize width2
519 (fsrc, code) <- getSomeReg x
520 fdst <- getNewRegNat fsize2
525 -- convert float to int format, leaving it in a float reg.
526 [ FxTOy fsize1 isize2 fsrc fdst
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]
533 return (Any isize2 code2)
536 -- | Coerce a double precision floating point value to single precision.
537 coerceDbl2Flt :: CmmExpr -> NatM Register
539 (src, code) <- getSomeReg x
540 return (Any FF32 (\dst -> code `snocOL` FxTOy FF64 FF32 src dst))
543 -- | Coerce a single precision floating point value to double precision
544 coerceFlt2Dbl :: CmmExpr -> NatM Register
546 (src, code) <- getSomeReg x
547 return (Any FF64 (\dst -> code `snocOL` FxTOy FF32 FF64 src dst))
552 -- Condition Codes -------------------------------------------------------------
554 -- Evaluate a comparision, and get the result into a register.
556 -- Do not fill the delay slots here. you will confuse the register allocator.
558 condIntReg :: Cond -> CmmExpr -> CmmExpr -> NatM Register
559 condIntReg EQQ x (CmmLit (CmmInt 0 _)) = do
560 (src, code) <- getSomeReg x
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)
567 condIntReg EQQ x y = do
568 (src1, code1) <- getSomeReg x
569 (src2, code2) <- getSomeReg y
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)
577 condIntReg NE x (CmmLit (CmmInt 0 _)) = do
578 (src, code) <- getSomeReg x
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)
585 condIntReg NE x y = do
586 (src1, code1) <- getSomeReg x
587 (src2, code2) <- getSomeReg y
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)
595 condIntReg cond x y = do
596 bid1@(BlockId _) <- getBlockIdNat
597 bid2@(BlockId _) <- getBlockIdNat
598 CondCode _ cond cond_code <- condIntCode cond x y
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,
605 OR False g0 (RIImm (ImmInt 1)) dst,
607 return (Any II32 code__2)
610 condFltReg :: Cond -> CmmExpr -> CmmExpr -> NatM Register
611 condFltReg cond x y = do
612 bid1@(BlockId _) <- getBlockIdNat
613 bid2@(BlockId _) <- getBlockIdNat
615 CondCode _ cond cond_code <- condFltCode cond x y
617 code__2 dst = cond_code `appOL` toOL [
619 BF cond False bid1, NOP,
620 OR False g0 (RIImm (ImmInt 0)) dst,
621 BI ALWAYS False bid2, NOP,
623 OR False g0 (RIImm (ImmInt 1)) dst,
625 return (Any II32 code__2)