2 -- | Expand out synthetic instructions into single machine instrs.
3 module SPARC.CodeGen.Expand (
23 -- | Expand out synthetic instructions in this top level thing
24 expandTop :: NatCmmTop Instr -> NatCmmTop Instr
25 expandTop top@(CmmData{})
28 expandTop (CmmProc info lbl params (ListGraph blocks))
29 = CmmProc info lbl params (ListGraph $ map expandBlock blocks)
32 -- | Expand out synthetic instructions in this block
33 expandBlock :: NatBasicBlock Instr -> NatBasicBlock Instr
35 expandBlock (BasicBlock label instrs)
36 = let instrs_ol = expandBlockInstrs instrs
37 instrs' = fromOL instrs_ol
38 in BasicBlock label instrs'
41 -- | Expand out some instructions
42 expandBlockInstrs :: [Instr] -> OrdList Instr
43 expandBlockInstrs [] = nilOL
45 expandBlockInstrs (ii:is)
46 = let ii_doubleRegs = remapRegPair ii
47 is_misaligned = expandMisalignedDoubles ii_doubleRegs
49 in is_misaligned `appOL` expandBlockInstrs is
53 -- | In the SPARC instruction set the FP register pairs that are used
54 -- to hold 64 bit floats are refered to by just the first reg
55 -- of the pair. Remap our internal reg pairs to the appropriate reg.
58 -- ldd [%l1], (%f0 | %f1)
63 remapRegPair :: Instr -> Instr
67 RegReal (RealRegSingle _)
70 RegReal (RealRegPair r1 r2)
77 -> RegReal (RealRegSingle r1)
80 -> pprPanic "SPARC.CodeGen.Expand: not remapping dodgy looking reg pair " (ppr reg)
83 -> pprPanic "SPARC.CodeGen.Expand: not remapping virtual reg " (ppr reg)
85 in patchRegsOfInstr instr patchF
90 -- Expand out 64 bit load/stores into individual instructions to handle
91 -- possible double alignment problems.
93 -- TODO: It'd be better to use a scratch reg instead of the add/sub thing.
94 -- We might be able to do this faster if we use the UA2007 instr set
95 -- instead of restricting ourselves to SPARC V9.
97 expandMisalignedDoubles :: Instr -> OrdList Instr
98 expandMisalignedDoubles instr
104 -- sub g1,g2,g1 -- to restore g1
105 | LD FF64 (AddrRegReg r1 r2) fReg <- instr
106 = toOL [ ADD False False r1 (RIReg r2) r1
107 , LD FF32 (AddrRegReg r1 g0) fReg
108 , LD FF32 (AddrRegImm r1 (ImmInt 4)) (fRegHi fReg)
109 , SUB False False r1 (RIReg r2) r1 ]
113 -- ld [addr+4],%f(n+1)
114 | LD FF64 addr fReg <- instr
115 = let Just addr' = addrOffset addr 4
116 in toOL [ LD FF32 addr fReg
117 , LD FF32 addr' (fRegHi fReg) ]
123 -- sub g1,g2,g1 -- to restore g1
124 | ST FF64 fReg (AddrRegReg r1 r2) <- instr
125 = toOL [ ADD False False r1 (RIReg r2) r1
126 , ST FF32 fReg (AddrRegReg r1 g0)
127 , ST FF32 (fRegHi fReg) (AddrRegImm r1 (ImmInt 4))
128 , SUB False False r1 (RIReg r2) r1 ]
132 -- ld [addr+4],%f(n+1)
133 | ST FF64 fReg addr <- instr
134 = let Just addr' = addrOffset addr 4
135 in toOL [ ST FF32 fReg addr
136 , ST FF32 (fRegHi fReg) addr' ]
144 -- | The the high partner for this float reg.
146 fRegHi (RegReal (RealRegSingle r1))
150 = (RegReal $ RealRegSingle (r1 + 1))
152 -- Can't take high partner for non-low reg.
154 = pprPanic "SPARC.CodeGen.Expand: can't take fRegHi from " (ppr reg)