NCG: Split up the native code generator into arch specific modules
[ghc-hetmet.git] / compiler / nativeGen / SPARC / Instr.hs
1 -----------------------------------------------------------------------------
2 --
3 -- Machine-dependent assembly language
4 --
5 -- (c) The University of Glasgow 1993-2004
6 --
7 -----------------------------------------------------------------------------
8
9 #include "HsVersions.h"
10 #include "nativeGen/NCG.h"
11
12 module SPARC.Instr (
13         RI(..),
14         Instr(..),
15         maxSpillSlots
16 )
17
18 where
19
20 import SPARC.Regs
21 import SPARC.Cond
22 import Instruction
23 import RegClass
24 import Reg
25 import Size
26
27 import BlockId
28 import Cmm
29 import Outputable
30 import Constants        (rESERVED_C_STACK_BYTES )
31 import FastString
32 import FastBool
33
34 import GHC.Exts
35
36
37 -- | Register or immediate
38 data RI 
39         = RIReg Reg
40         | RIImm Imm
41
42
43 -- | instance for sparc instruction set
44 instance Instruction Instr where
45         regUsageOfInstr         = sparc_regUsageOfInstr
46         patchRegsOfInstr        = sparc_patchRegsOfInstr
47         isJumpishInstr          = sparc_isJumpishInstr
48         jumpDestsOfInstr        = sparc_jumpDestsOfInstr
49         patchJumpInstr          = sparc_patchJumpInstr
50         mkSpillInstr            = sparc_mkSpillInstr
51         mkLoadInstr             = sparc_mkLoadInstr
52         takeDeltaInstr          = sparc_takeDeltaInstr
53         isMetaInstr             = sparc_isMetaInstr
54         mkRegRegMoveInstr       = sparc_mkRegRegMoveInstr
55         takeRegRegMoveInstr     = sparc_takeRegRegMoveInstr
56         mkJumpInstr             = sparc_mkJumpInstr
57
58
59 -- | SPARC instruction set.
60 --      Not complete. This is only the ones we need.
61 --
62 data Instr
63
64         -- meta ops --------------------------------------------------
65         -- comment pseudo-op
66         = COMMENT FastString            
67
68         -- some static data spat out during code generation.
69         -- Will be extracted before pretty-printing.
70         | LDATA   Section [CmmStatic]   
71
72         -- Start a new basic block.  Useful during codegen, removed later.
73         -- Preceding instruction should be a jump, as per the invariants
74         -- for a BasicBlock (see Cmm).
75         | NEWBLOCK BlockId              
76
77         -- specify current stack offset for benefit of subsequent passes.
78         | DELTA   Int
79
80         -- real instrs -----------------------------------------------
81         -- Loads and stores.
82         | LD            Size AddrMode Reg               -- size, src, dst
83         | ST            Size Reg AddrMode               -- size, src, dst
84
85         -- Int Arithmetic.
86         | ADD           Bool Bool Reg RI Reg            -- x?, cc?, src1, src2, dst
87         | SUB           Bool Bool Reg RI Reg            -- x?, cc?, src1, src2, dst
88
89         | UMUL          Bool Reg RI Reg                 --     cc?, src1, src2, dst
90         | SMUL          Bool Reg RI Reg                 --     cc?, src1, src2, dst
91
92
93         -- The SPARC divide instructions perform 64bit by 32bit division
94         --   The Y register is xored into the first operand.
95
96         --   On _some implementations_ the Y register is overwritten by
97         --   the remainder, so we have to make sure it is 0 each time.
98
99         --   dst <- ((Y `shiftL` 32) `or` src1) `div` src2
100         | UDIV          Bool Reg RI Reg                 --     cc?, src1, src2, dst
101         | SDIV          Bool Reg RI Reg                 --     cc?, src1, src2, dst
102
103         | RDY           Reg                             -- move contents of Y register to reg
104         | WRY           Reg  Reg                        -- Y <- src1 `xor` src2
105         
106         -- Logic operations.
107         | AND           Bool Reg RI Reg                 -- cc?, src1, src2, dst
108         | ANDN          Bool Reg RI Reg                 -- cc?, src1, src2, dst
109         | OR            Bool Reg RI Reg                 -- cc?, src1, src2, dst
110         | ORN           Bool Reg RI Reg                 -- cc?, src1, src2, dst
111         | XOR           Bool Reg RI Reg                 -- cc?, src1, src2, dst
112         | XNOR          Bool Reg RI Reg                 -- cc?, src1, src2, dst
113         | SLL           Reg RI Reg                      -- src1, src2, dst
114         | SRL           Reg RI Reg                      -- src1, src2, dst
115         | SRA           Reg RI Reg                      -- src1, src2, dst
116
117         -- Load immediates.
118         | SETHI         Imm Reg                         -- src, dst
119
120         -- Do nothing.
121         -- Implemented by the assembler as SETHI 0, %g0, but worth an alias
122         | NOP                                           
123
124         -- Float Arithmetic.
125         -- Note that we cheat by treating F{ABS,MOV,NEG} of doubles as single
126         -- instructions right up until we spit them out.
127         --
128         | FABS          Size Reg Reg                    -- src dst
129         | FADD          Size Reg Reg Reg                -- src1, src2, dst
130         | FCMP          Bool Size Reg Reg               -- exception?, src1, src2, dst
131         | FDIV          Size Reg Reg Reg                -- src1, src2, dst
132         | FMOV          Size Reg Reg                    -- src, dst
133         | FMUL          Size Reg Reg Reg                -- src1, src2, dst
134         | FNEG          Size Reg Reg                    -- src, dst
135         | FSQRT         Size Reg Reg                    -- src, dst
136         | FSUB          Size Reg Reg Reg                -- src1, src2, dst
137         | FxTOy         Size Size Reg Reg               -- src, dst
138
139         -- Jumping around.
140         | BI            Cond Bool BlockId               -- cond, annul?, target
141         | BF            Cond Bool BlockId               -- cond, annul?, target
142
143         | JMP           AddrMode                        -- target
144
145         -- With a tabled jump we know all the possible destinations.
146         -- We also need this info so we can work out what regs are live across the jump.
147         -- 
148         | JMP_TBL       AddrMode [BlockId]
149
150         | CALL          (Either Imm Reg) Int Bool       -- target, args, terminal
151
152
153 -- | regUsage returns the sets of src and destination registers used
154 --      by a particular instruction.  Machine registers that are
155 --      pre-allocated to stgRegs are filtered out, because they are
156 --      uninteresting from a register allocation standpoint.  (We wouldn't
157 --      want them to end up on the free list!)  As far as we are concerned,
158 --      the fixed registers simply don't exist (for allocation purposes,
159 --      anyway).
160
161 --      regUsage doesn't need to do any trickery for jumps and such.  Just
162 --      state precisely the regs read and written by that insn.  The
163 --      consequences of control flow transfers, as far as register
164 --      allocation goes, are taken care of by the register allocator.
165 --
166 sparc_regUsageOfInstr :: Instr -> RegUsage
167 sparc_regUsageOfInstr instr 
168  = case instr of
169     LD    _ addr reg            -> usage (regAddr addr,         [reg])
170     ST    _ reg addr            -> usage (reg : regAddr addr,   [])
171     ADD   _ _ r1 ar r2          -> usage (r1 : regRI ar,        [r2])
172     SUB   _ _ r1 ar r2          -> usage (r1 : regRI ar,        [r2])
173     UMUL    _ r1 ar r2          -> usage (r1 : regRI ar,        [r2])
174     SMUL    _ r1 ar r2          -> usage (r1 : regRI ar,        [r2])
175     UDIV    _ r1 ar r2          -> usage (r1 : regRI ar,        [r2])
176     SDIV    _ r1 ar r2          -> usage (r1 : regRI ar,        [r2])
177     RDY       rd                -> usage ([],                   [rd])
178     WRY       r1 r2             -> usage ([r1, r2],             [])
179     AND     _ r1 ar r2          -> usage (r1 : regRI ar,        [r2])
180     ANDN    _ r1 ar r2          -> usage (r1 : regRI ar,        [r2])
181     OR      _ r1 ar r2          -> usage (r1 : regRI ar,        [r2])
182     ORN     _ r1 ar r2          -> usage (r1 : regRI ar,        [r2])
183     XOR     _ r1 ar r2          -> usage (r1 : regRI ar,        [r2])
184     XNOR    _ r1 ar r2          -> usage (r1 : regRI ar,        [r2])
185     SLL       r1 ar r2          -> usage (r1 : regRI ar,        [r2])
186     SRL       r1 ar r2          -> usage (r1 : regRI ar,        [r2])
187     SRA       r1 ar r2          -> usage (r1 : regRI ar,        [r2])
188     SETHI   _ reg               -> usage ([],                   [reg])
189     FABS    _ r1 r2             -> usage ([r1],                 [r2])
190     FADD    _ r1 r2 r3          -> usage ([r1, r2],             [r3])
191     FCMP    _ _  r1 r2          -> usage ([r1, r2],             [])
192     FDIV    _ r1 r2 r3          -> usage ([r1, r2],             [r3])
193     FMOV    _ r1 r2             -> usage ([r1],                 [r2])
194     FMUL    _ r1 r2 r3          -> usage ([r1, r2],             [r3])
195     FNEG    _ r1 r2             -> usage ([r1],                 [r2])
196     FSQRT   _ r1 r2             -> usage ([r1],                 [r2])
197     FSUB    _ r1 r2 r3          -> usage ([r1, r2],             [r3])
198     FxTOy   _ _  r1 r2          -> usage ([r1],                 [r2])
199
200     JMP     addr                -> usage (regAddr addr, [])
201     JMP_TBL addr _              -> usage (regAddr addr, [])
202
203     CALL  (Left _  )  _ True    -> noUsage
204     CALL  (Left _  )  n False   -> usage (argRegs n, callClobberedRegs)
205     CALL  (Right reg) _ True    -> usage ([reg], [])
206     CALL  (Right reg) n False   -> usage (reg : (argRegs n), callClobberedRegs)
207     _                           -> noUsage
208
209   where
210     usage (src, dst) 
211      = RU (filter interesting src) (filter interesting dst)
212
213     regAddr (AddrRegReg r1 r2)  = [r1, r2]
214     regAddr (AddrRegImm r1 _)   = [r1]
215
216     regRI (RIReg r)             = [r]
217     regRI  _                    = []
218
219
220 -- | Interesting regs are virtuals, or ones that are allocatable 
221 --      by the register allocator.
222 interesting :: Reg -> Bool
223 interesting reg
224  = case reg of
225         VirtualRegI  _  -> True
226         VirtualRegHi _  -> True
227         VirtualRegF  _  -> True
228         VirtualRegD  _  -> True
229         RealReg i       -> isFastTrue (freeReg i)
230
231
232
233 -- | Apply a given mapping to tall the register references in this instruction.
234 sparc_patchRegsOfInstr :: Instr -> (Reg -> Reg) -> Instr
235 sparc_patchRegsOfInstr instr env = case instr of
236     LD    sz addr reg           -> LD sz (fixAddr addr) (env reg)
237     ST    sz reg addr           -> ST sz (env reg) (fixAddr addr)
238
239     ADD   x cc r1 ar r2         -> ADD   x cc  (env r1) (fixRI ar) (env r2)
240     SUB   x cc r1 ar r2         -> SUB   x cc  (env r1) (fixRI ar) (env r2)
241     UMUL    cc r1 ar r2         -> UMUL    cc  (env r1) (fixRI ar) (env r2)
242     SMUL    cc r1 ar r2         -> SMUL    cc  (env r1) (fixRI ar) (env r2)
243     UDIV    cc r1 ar r2         -> UDIV    cc  (env r1) (fixRI ar) (env r2)
244     SDIV    cc r1 ar r2         -> SDIV    cc  (env r1) (fixRI ar) (env r2)
245     RDY   rd                    -> RDY         (env rd)
246     WRY   r1 r2                 -> WRY         (env r1) (env r2)
247     AND   b r1 ar r2            -> AND   b     (env r1) (fixRI ar) (env r2)
248     ANDN  b r1 ar r2            -> ANDN  b     (env r1) (fixRI ar) (env r2)
249     OR    b r1 ar r2            -> OR    b     (env r1) (fixRI ar) (env r2)
250     ORN   b r1 ar r2            -> ORN   b     (env r1) (fixRI ar) (env r2)
251     XOR   b r1 ar r2            -> XOR   b     (env r1) (fixRI ar) (env r2)
252     XNOR  b r1 ar r2            -> XNOR  b     (env r1) (fixRI ar) (env r2)
253     SLL   r1 ar r2              -> SLL         (env r1) (fixRI ar) (env r2)
254     SRL   r1 ar r2              -> SRL         (env r1) (fixRI ar) (env r2)
255     SRA   r1 ar r2              -> SRA         (env r1) (fixRI ar) (env r2)
256
257     SETHI imm reg               -> SETHI imm (env reg)
258
259     FABS  s r1 r2               -> FABS    s   (env r1) (env r2)
260     FADD  s r1 r2 r3            -> FADD    s   (env r1) (env r2) (env r3)
261     FCMP  e s r1 r2             -> FCMP e  s   (env r1) (env r2)
262     FDIV  s r1 r2 r3            -> FDIV    s   (env r1) (env r2) (env r3)
263     FMOV  s r1 r2               -> FMOV    s   (env r1) (env r2)
264     FMUL  s r1 r2 r3            -> FMUL    s   (env r1) (env r2) (env r3)
265     FNEG  s r1 r2               -> FNEG    s   (env r1) (env r2)
266     FSQRT s r1 r2               -> FSQRT   s   (env r1) (env r2)
267     FSUB  s r1 r2 r3            -> FSUB    s   (env r1) (env r2) (env r3)
268     FxTOy s1 s2 r1 r2           -> FxTOy s1 s2 (env r1) (env r2)
269
270     JMP     addr                -> JMP     (fixAddr addr)
271     JMP_TBL addr ids            -> JMP_TBL (fixAddr addr) ids
272
273     CALL  (Left i) n t          -> CALL (Left i) n t
274     CALL  (Right r) n t         -> CALL (Right (env r)) n t
275     _                           -> instr
276
277   where
278     fixAddr (AddrRegReg r1 r2)  = AddrRegReg   (env r1) (env r2)
279     fixAddr (AddrRegImm r1 i)   = AddrRegImm   (env r1) i
280
281     fixRI (RIReg r)             = RIReg (env r)
282     fixRI other                 = other
283
284
285 --------------------------------------------------------------------------------
286 sparc_isJumpishInstr :: Instr -> Bool
287 sparc_isJumpishInstr instr
288  = case instr of
289         BI{}            -> True
290         BF{}            -> True
291         JMP{}           -> True
292         JMP_TBL{}       -> True
293         CALL{}          -> True
294         _               -> False
295
296 sparc_jumpDestsOfInstr :: Instr -> [BlockId]
297 sparc_jumpDestsOfInstr insn
298   = case insn of
299         BI   _ _ id     -> [id]
300         BF   _ _ id     -> [id]
301         JMP_TBL _ ids   -> ids
302         _               -> []
303
304
305 sparc_patchJumpInstr :: Instr -> (BlockId -> BlockId) -> Instr
306 sparc_patchJumpInstr insn patchF
307   = case insn of
308         BI cc annul id  -> BI cc annul (patchF id)
309         BF cc annul id  -> BF cc annul (patchF id)
310         _               -> insn
311
312
313 --------------------------------------------------------------------------------
314 -- | Make a spill instruction.
315 --      On SPARC we spill below frame pointer leaving 2 words/spill
316 sparc_mkSpillInstr
317         :: Reg          -- ^ register to spill
318         -> Int          -- ^ current stack delta
319         -> Int          -- ^ spill slot to use
320         -> Instr
321
322 sparc_mkSpillInstr reg _ slot
323  = let  off     = spillSlotToOffset slot
324         off_w   = 1 + (off `div` 4)
325         sz      = case regClass reg of
326                         RcInteger -> II32
327                         RcFloat   -> FF32
328                         RcDouble  -> FF64
329                 
330     in ST sz reg (fpRel (negate off_w))
331
332
333 -- | Make a spill reload instruction.
334 sparc_mkLoadInstr
335         :: Reg          -- ^ register to load
336         -> Int          -- ^ current stack delta
337         -> Int          -- ^ spill slot to use
338         -> Instr
339
340 sparc_mkLoadInstr reg _ slot
341   = let off     = spillSlotToOffset slot
342         off_w   = 1 + (off `div` 4)
343         sz      = case regClass reg of
344                         RcInteger -> II32
345                         RcFloat   -> FF32
346                         RcDouble  -> FF64
347
348         in LD sz (fpRel (- off_w)) reg
349
350 -- | Convert a spill slot number to a *byte* offset, with no sign.
351 --
352 spillSlotToOffset :: Int -> Int
353 spillSlotToOffset slot
354         | slot >= 0 && slot < maxSpillSlots
355         = 64 + spillSlotSize * slot
356
357         | otherwise
358         = pprPanic "spillSlotToOffset:" 
359                       (   text "invalid spill location: " <> int slot
360                       $$  text "maxSpillSlots:          " <> int maxSpillSlots)
361
362
363 -- | We need 8 bytes because our largest registers are 64 bit.
364 spillSlotSize :: Int
365 spillSlotSize = 8
366
367
368 -- | The maximum number of spill slots available on the C stack.
369 --      If we use up all of the slots, then we're screwed.
370 maxSpillSlots :: Int
371 maxSpillSlots = ((rESERVED_C_STACK_BYTES - 64) `div` spillSlotSize) - 1
372
373
374 --------------------------------------------------------------------------------
375 -- | See if this instruction is telling us the current C stack delta
376 sparc_takeDeltaInstr
377         :: Instr
378         -> Maybe Int
379         
380 sparc_takeDeltaInstr instr
381  = case instr of
382         DELTA i         -> Just i
383         _               -> Nothing
384
385
386 sparc_isMetaInstr
387         :: Instr
388         -> Bool
389         
390 sparc_isMetaInstr instr
391  = case instr of
392         COMMENT{}       -> True
393         LDATA{}         -> True
394         NEWBLOCK{}      -> True
395         DELTA{}         -> True
396         _               -> False
397         
398
399 -- | Make a reg-reg move instruction.
400 --      On SPARC v8 there are no instructions to move directly between
401 --      floating point and integer regs. If we need to do that then we
402 --      have to go via memory.
403 --
404 sparc_mkRegRegMoveInstr
405         :: Reg
406         -> Reg
407         -> Instr
408
409 sparc_mkRegRegMoveInstr src dst
410  = case regClass src of
411         RcInteger -> ADD  False False src (RIReg g0) dst
412         RcDouble  -> FMOV FF64 src dst
413         RcFloat   -> FMOV FF32 src dst
414
415
416 -- | Check whether an instruction represents a reg-reg move.
417 --      The register allocator attempts to eliminate reg->reg moves whenever it can,
418 --      by assigning the src and dest temporaries to the same real register.
419 --
420 sparc_takeRegRegMoveInstr :: Instr -> Maybe (Reg,Reg)
421 sparc_takeRegRegMoveInstr instr
422  = case instr of
423         ADD False False src (RIReg src2) dst
424          | g0 == src2           -> Just (src, dst)
425
426         FMOV FF64 src dst       -> Just (src, dst)
427         FMOV FF32  src dst      -> Just (src, dst)
428         _                       -> Nothing
429
430
431 -- | Make an unconditional branch instruction.
432 sparc_mkJumpInstr
433         :: BlockId
434         -> [Instr]
435
436 sparc_mkJumpInstr id 
437  =       [BI ALWAYS False id
438         , NOP]                  -- fill the branch delay slot.
439