1 -----------------------------------------------------------------------------
3 -- Machine-dependent assembly language
5 -- (c) The University of Glasgow 1993-2004
7 -----------------------------------------------------------------------------
9 #include "HsVersions.h"
10 #include "nativeGen/NCG.h"
48 -- | Register or immediate
53 -- | Check if a RI represents a zero value.
55 -- - register %g0, which is always zero.
58 riZero (RIImm (ImmInt 0)) = True
59 riZero (RIImm (ImmInteger 0)) = True
60 riZero (RIReg (RegReal (RealRegSingle 0))) = True
64 -- | Calculate the effective address which would be used by the
65 -- corresponding fpRel sequence.
66 fpRelEA :: Int -> Reg -> Instr
68 = ADD False False fp (RIImm (ImmInt (n * wordLength))) dst
71 -- | Code to shift the stack pointer by n words.
72 moveSp :: Int -> Instr
74 = ADD False False sp (RIImm (ImmInt (n * wordLength))) sp
76 -- | An instruction that will cause the one after it never to be exectuted
77 isUnconditionalJump :: Instr -> Bool
78 isUnconditionalJump ii
88 -- | instance for sparc instruction set
89 instance Instruction Instr where
90 regUsageOfInstr = sparc_regUsageOfInstr
91 patchRegsOfInstr = sparc_patchRegsOfInstr
92 isJumpishInstr = sparc_isJumpishInstr
93 jumpDestsOfInstr = sparc_jumpDestsOfInstr
94 patchJumpInstr = sparc_patchJumpInstr
95 mkSpillInstr = sparc_mkSpillInstr
96 mkLoadInstr = sparc_mkLoadInstr
97 takeDeltaInstr = sparc_takeDeltaInstr
98 isMetaInstr = sparc_isMetaInstr
99 mkRegRegMoveInstr = sparc_mkRegRegMoveInstr
100 takeRegRegMoveInstr = sparc_takeRegRegMoveInstr
101 mkJumpInstr = sparc_mkJumpInstr
104 -- | SPARC instruction set.
105 -- Not complete. This is only the ones we need.
109 -- meta ops --------------------------------------------------
113 -- some static data spat out during code generation.
114 -- Will be extracted before pretty-printing.
115 | LDATA Section [CmmStatic]
117 -- Start a new basic block. Useful during codegen, removed later.
118 -- Preceding instruction should be a jump, as per the invariants
119 -- for a BasicBlock (see Cmm).
122 -- specify current stack offset for benefit of subsequent passes.
125 -- real instrs -----------------------------------------------
127 | LD Size AddrMode Reg -- size, src, dst
128 | ST Size Reg AddrMode -- size, src, dst
131 -- x: add/sub with carry bit.
132 -- In SPARC V9 addx and friends were renamed addc.
134 -- cc: modify condition codes
136 | ADD Bool Bool Reg RI Reg -- x?, cc?, src1, src2, dst
137 | SUB Bool Bool Reg RI Reg -- x?, cc?, src1, src2, dst
139 | UMUL Bool Reg RI Reg -- cc?, src1, src2, dst
140 | SMUL Bool Reg RI Reg -- cc?, src1, src2, dst
143 -- The SPARC divide instructions perform 64bit by 32bit division
144 -- The Y register is xored into the first operand.
146 -- On _some implementations_ the Y register is overwritten by
147 -- the remainder, so we have to make sure it is 0 each time.
149 -- dst <- ((Y `shiftL` 32) `or` src1) `div` src2
150 | UDIV Bool Reg RI Reg -- cc?, src1, src2, dst
151 | SDIV Bool Reg RI Reg -- cc?, src1, src2, dst
153 | RDY Reg -- move contents of Y register to reg
154 | WRY Reg Reg -- Y <- src1 `xor` src2
157 | AND Bool Reg RI Reg -- cc?, src1, src2, dst
158 | ANDN Bool Reg RI Reg -- cc?, src1, src2, dst
159 | OR Bool Reg RI Reg -- cc?, src1, src2, dst
160 | ORN Bool Reg RI Reg -- cc?, src1, src2, dst
161 | XOR Bool Reg RI Reg -- cc?, src1, src2, dst
162 | XNOR Bool Reg RI Reg -- cc?, src1, src2, dst
163 | SLL Reg RI Reg -- src1, src2, dst
164 | SRL Reg RI Reg -- src1, src2, dst
165 | SRA Reg RI Reg -- src1, src2, dst
168 | SETHI Imm Reg -- src, dst
171 -- Implemented by the assembler as SETHI 0, %g0, but worth an alias
175 -- Note that we cheat by treating F{ABS,MOV,NEG} of doubles as single
176 -- instructions right up until we spit them out.
178 | FABS Size Reg Reg -- src dst
179 | FADD Size Reg Reg Reg -- src1, src2, dst
180 | FCMP Bool Size Reg Reg -- exception?, src1, src2, dst
181 | FDIV Size Reg Reg Reg -- src1, src2, dst
182 | FMOV Size Reg Reg -- src, dst
183 | FMUL Size Reg Reg Reg -- src1, src2, dst
184 | FNEG Size Reg Reg -- src, dst
185 | FSQRT Size Reg Reg -- src, dst
186 | FSUB Size Reg Reg Reg -- src1, src2, dst
187 | FxTOy Size Size Reg Reg -- src, dst
190 | BI Cond Bool BlockId -- cond, annul?, target
191 | BF Cond Bool BlockId -- cond, annul?, target
193 | JMP AddrMode -- target
195 -- With a tabled jump we know all the possible destinations.
196 -- We also need this info so we can work out what regs are live across the jump.
198 | JMP_TBL AddrMode [Maybe BlockId] CLabel
200 | CALL (Either Imm Reg) Int Bool -- target, args, terminal
203 -- | regUsage returns the sets of src and destination registers used
204 -- by a particular instruction. Machine registers that are
205 -- pre-allocated to stgRegs are filtered out, because they are
206 -- uninteresting from a register allocation standpoint. (We wouldn't
207 -- want them to end up on the free list!) As far as we are concerned,
208 -- the fixed registers simply don't exist (for allocation purposes,
211 -- regUsage doesn't need to do any trickery for jumps and such. Just
212 -- state precisely the regs read and written by that insn. The
213 -- consequences of control flow transfers, as far as register
214 -- allocation goes, are taken care of by the register allocator.
216 sparc_regUsageOfInstr :: Instr -> RegUsage
217 sparc_regUsageOfInstr instr
219 LD _ addr reg -> usage (regAddr addr, [reg])
220 ST _ reg addr -> usage (reg : regAddr addr, [])
221 ADD _ _ r1 ar r2 -> usage (r1 : regRI ar, [r2])
222 SUB _ _ r1 ar r2 -> usage (r1 : regRI ar, [r2])
223 UMUL _ r1 ar r2 -> usage (r1 : regRI ar, [r2])
224 SMUL _ r1 ar r2 -> usage (r1 : regRI ar, [r2])
225 UDIV _ r1 ar r2 -> usage (r1 : regRI ar, [r2])
226 SDIV _ r1 ar r2 -> usage (r1 : regRI ar, [r2])
227 RDY rd -> usage ([], [rd])
228 WRY r1 r2 -> usage ([r1, r2], [])
229 AND _ r1 ar r2 -> usage (r1 : regRI ar, [r2])
230 ANDN _ r1 ar r2 -> usage (r1 : regRI ar, [r2])
231 OR _ r1 ar r2 -> usage (r1 : regRI ar, [r2])
232 ORN _ r1 ar r2 -> usage (r1 : regRI ar, [r2])
233 XOR _ r1 ar r2 -> usage (r1 : regRI ar, [r2])
234 XNOR _ r1 ar r2 -> usage (r1 : regRI ar, [r2])
235 SLL r1 ar r2 -> usage (r1 : regRI ar, [r2])
236 SRL r1 ar r2 -> usage (r1 : regRI ar, [r2])
237 SRA r1 ar r2 -> usage (r1 : regRI ar, [r2])
238 SETHI _ reg -> usage ([], [reg])
239 FABS _ r1 r2 -> usage ([r1], [r2])
240 FADD _ r1 r2 r3 -> usage ([r1, r2], [r3])
241 FCMP _ _ r1 r2 -> usage ([r1, r2], [])
242 FDIV _ r1 r2 r3 -> usage ([r1, r2], [r3])
243 FMOV _ r1 r2 -> usage ([r1], [r2])
244 FMUL _ r1 r2 r3 -> usage ([r1, r2], [r3])
245 FNEG _ r1 r2 -> usage ([r1], [r2])
246 FSQRT _ r1 r2 -> usage ([r1], [r2])
247 FSUB _ r1 r2 r3 -> usage ([r1, r2], [r3])
248 FxTOy _ _ r1 r2 -> usage ([r1], [r2])
250 JMP addr -> usage (regAddr addr, [])
251 JMP_TBL addr _ _ -> usage (regAddr addr, [])
253 CALL (Left _ ) _ True -> noUsage
254 CALL (Left _ ) n False -> usage (argRegs n, callClobberedRegs)
255 CALL (Right reg) _ True -> usage ([reg], [])
256 CALL (Right reg) n False -> usage (reg : (argRegs n), callClobberedRegs)
261 = RU (filter interesting src) (filter interesting dst)
263 regAddr (AddrRegReg r1 r2) = [r1, r2]
264 regAddr (AddrRegImm r1 _) = [r1]
266 regRI (RIReg r) = [r]
270 -- | Interesting regs are virtuals, or ones that are allocatable
271 -- by the register allocator.
272 interesting :: Reg -> Bool
276 RegReal (RealRegSingle r1) -> isFastTrue (freeReg r1)
277 RegReal (RealRegPair r1 _) -> isFastTrue (freeReg r1)
281 -- | Apply a given mapping to tall the register references in this instruction.
282 sparc_patchRegsOfInstr :: Instr -> (Reg -> Reg) -> Instr
283 sparc_patchRegsOfInstr instr env = case instr of
284 LD sz addr reg -> LD sz (fixAddr addr) (env reg)
285 ST sz reg addr -> ST sz (env reg) (fixAddr addr)
287 ADD x cc r1 ar r2 -> ADD x cc (env r1) (fixRI ar) (env r2)
288 SUB x cc r1 ar r2 -> SUB x cc (env r1) (fixRI ar) (env r2)
289 UMUL cc r1 ar r2 -> UMUL cc (env r1) (fixRI ar) (env r2)
290 SMUL cc r1 ar r2 -> SMUL cc (env r1) (fixRI ar) (env r2)
291 UDIV cc r1 ar r2 -> UDIV cc (env r1) (fixRI ar) (env r2)
292 SDIV cc r1 ar r2 -> SDIV cc (env r1) (fixRI ar) (env r2)
293 RDY rd -> RDY (env rd)
294 WRY r1 r2 -> WRY (env r1) (env r2)
295 AND b r1 ar r2 -> AND b (env r1) (fixRI ar) (env r2)
296 ANDN b r1 ar r2 -> ANDN b (env r1) (fixRI ar) (env r2)
297 OR b r1 ar r2 -> OR b (env r1) (fixRI ar) (env r2)
298 ORN b r1 ar r2 -> ORN b (env r1) (fixRI ar) (env r2)
299 XOR b r1 ar r2 -> XOR b (env r1) (fixRI ar) (env r2)
300 XNOR b r1 ar r2 -> XNOR b (env r1) (fixRI ar) (env r2)
301 SLL r1 ar r2 -> SLL (env r1) (fixRI ar) (env r2)
302 SRL r1 ar r2 -> SRL (env r1) (fixRI ar) (env r2)
303 SRA r1 ar r2 -> SRA (env r1) (fixRI ar) (env r2)
305 SETHI imm reg -> SETHI imm (env reg)
307 FABS s r1 r2 -> FABS s (env r1) (env r2)
308 FADD s r1 r2 r3 -> FADD s (env r1) (env r2) (env r3)
309 FCMP e s r1 r2 -> FCMP e s (env r1) (env r2)
310 FDIV s r1 r2 r3 -> FDIV s (env r1) (env r2) (env r3)
311 FMOV s r1 r2 -> FMOV s (env r1) (env r2)
312 FMUL s r1 r2 r3 -> FMUL s (env r1) (env r2) (env r3)
313 FNEG s r1 r2 -> FNEG s (env r1) (env r2)
314 FSQRT s r1 r2 -> FSQRT s (env r1) (env r2)
315 FSUB s r1 r2 r3 -> FSUB s (env r1) (env r2) (env r3)
316 FxTOy s1 s2 r1 r2 -> FxTOy s1 s2 (env r1) (env r2)
318 JMP addr -> JMP (fixAddr addr)
319 JMP_TBL addr ids l -> JMP_TBL (fixAddr addr) ids l
321 CALL (Left i) n t -> CALL (Left i) n t
322 CALL (Right r) n t -> CALL (Right (env r)) n t
326 fixAddr (AddrRegReg r1 r2) = AddrRegReg (env r1) (env r2)
327 fixAddr (AddrRegImm r1 i) = AddrRegImm (env r1) i
329 fixRI (RIReg r) = RIReg (env r)
333 --------------------------------------------------------------------------------
334 sparc_isJumpishInstr :: Instr -> Bool
335 sparc_isJumpishInstr instr
344 sparc_jumpDestsOfInstr :: Instr -> [BlockId]
345 sparc_jumpDestsOfInstr insn
349 JMP_TBL _ ids _ -> [id | Just id <- ids]
353 sparc_patchJumpInstr :: Instr -> (BlockId -> BlockId) -> Instr
354 sparc_patchJumpInstr insn patchF
356 BI cc annul id -> BI cc annul (patchF id)
357 BF cc annul id -> BF cc annul (patchF id)
358 JMP_TBL n ids l -> JMP_TBL n (map (fmap patchF) ids) l
362 --------------------------------------------------------------------------------
363 -- | Make a spill instruction.
364 -- On SPARC we spill below frame pointer leaving 2 words/spill
366 :: Reg -- ^ register to spill
367 -> Int -- ^ current stack delta
368 -> Int -- ^ spill slot to use
371 sparc_mkSpillInstr reg _ slot
372 = let off = spillSlotToOffset slot
373 off_w = 1 + (off `div` 4)
374 sz = case targetClassOfReg reg of
378 _ -> panic "sparc_mkSpillInstr"
380 in ST sz reg (fpRel (negate off_w))
383 -- | Make a spill reload instruction.
385 :: Reg -- ^ register to load into
386 -> Int -- ^ current stack delta
387 -> Int -- ^ spill slot to use
390 sparc_mkLoadInstr reg _ slot
391 = let off = spillSlotToOffset slot
392 off_w = 1 + (off `div` 4)
393 sz = case targetClassOfReg reg of
397 _ -> panic "sparc_mkLoadInstr"
399 in LD sz (fpRel (- off_w)) reg
402 --------------------------------------------------------------------------------
403 -- | See if this instruction is telling us the current C stack delta
408 sparc_takeDeltaInstr instr
418 sparc_isMetaInstr instr
427 -- | Make a reg-reg move instruction.
428 -- On SPARC v8 there are no instructions to move directly between
429 -- floating point and integer regs. If we need to do that then we
430 -- have to go via memory.
432 sparc_mkRegRegMoveInstr
437 sparc_mkRegRegMoveInstr src dst
438 | srcClass <- targetClassOfReg src
439 , dstClass <- targetClassOfReg dst
440 , srcClass == dstClass
442 RcInteger -> ADD False False src (RIReg g0) dst
443 RcDouble -> FMOV FF64 src dst
444 RcFloat -> FMOV FF32 src dst
445 _ -> panic "sparc_mkRegRegMoveInstr"
448 = panic "SPARC.Instr.mkRegRegMoveInstr: classes of src and dest not the same"
451 -- | Check whether an instruction represents a reg-reg move.
452 -- The register allocator attempts to eliminate reg->reg moves whenever it can,
453 -- by assigning the src and dest temporaries to the same real register.
455 sparc_takeRegRegMoveInstr :: Instr -> Maybe (Reg,Reg)
456 sparc_takeRegRegMoveInstr instr
458 ADD False False src (RIReg src2) dst
459 | g0 == src2 -> Just (src, dst)
461 FMOV FF64 src dst -> Just (src, dst)
462 FMOV FF32 src dst -> Just (src, dst)
466 -- | Make an unconditional branch instruction.
472 = [BI ALWAYS False id
473 , NOP] -- fill the branch delay slot.