1 -----------------------------------------------------------------------------
3 -- Machine-dependent assembly language
5 -- (c) The University of Glasgow 1993-2004
7 -----------------------------------------------------------------------------
9 #include "HsVersions.h"
10 #include "nativeGen/NCG.h"
29 import Constants (rESERVED_C_STACK_BYTES)
37 --------------------------------------------------------------------------------
38 -- Size of a PPC memory address, in bytes.
44 -- | Instruction instance for powerpc
45 instance Instruction Instr where
46 regUsageOfInstr = ppc_regUsageOfInstr
47 patchRegsOfInstr = ppc_patchRegsOfInstr
48 isJumpishInstr = ppc_isJumpishInstr
49 jumpDestsOfInstr = ppc_jumpDestsOfInstr
50 patchJumpInstr = ppc_patchJumpInstr
51 mkSpillInstr = ppc_mkSpillInstr
52 mkLoadInstr = ppc_mkLoadInstr
53 takeDeltaInstr = ppc_takeDeltaInstr
54 isMetaInstr = ppc_isMetaInstr
55 mkRegRegMoveInstr = ppc_mkRegRegMoveInstr
56 takeRegRegMoveInstr = ppc_takeRegRegMoveInstr
57 mkJumpInstr = ppc_mkJumpInstr
60 -- -----------------------------------------------------------------------------
61 -- Machine's assembly language
63 -- We have a few common "instructions" (nearly all the pseudo-ops) but
64 -- mostly all of 'Instr' is machine-specific.
66 -- Register or immediate
75 -- some static data spat out during code
76 -- generation. Will be extracted before
78 | LDATA Section [CmmStatic]
80 -- start a new basic block. Useful during
81 -- codegen, removed later. Preceding
82 -- instruction should be a jump, as per the
83 -- invariants for a BasicBlock (see Cmm).
86 -- specify current stack offset for
87 -- benefit of subsequent passes
91 | LD Size Reg AddrMode -- Load size, dst, src
92 | LA Size Reg AddrMode -- Load arithmetic size, dst, src
93 | ST Size Reg AddrMode -- Store size, src, dst
94 | STU Size Reg AddrMode -- Store with Update size, src, dst
95 | LIS Reg Imm -- Load Immediate Shifted dst, src
96 | LI Reg Imm -- Load Immediate dst, src
97 | MR Reg Reg -- Move Register dst, src -- also for fmr
99 | CMP Size Reg RI --- size, src1, src2
100 | CMPL Size Reg RI --- size, src1, src2
103 | BCCFAR Cond BlockId
104 | JMP CLabel -- same as branch,
105 -- but with CLabel instead of block ID
107 | BCTR [Maybe BlockId] (Maybe CLabel) -- with list of local destinations, and jump table location if necessary
108 | BL CLabel [Reg] -- with list of argument regs
111 | ADD Reg Reg RI -- dst, src1, src2
112 | ADDC Reg Reg Reg -- (carrying) dst, src1, src2
113 | ADDE Reg Reg Reg -- (extend) dst, src1, src2
114 | ADDIS Reg Reg Imm -- Add Immediate Shifted dst, src1, src2
115 | SUBF Reg Reg Reg -- dst, src1, src2 ; dst = src2 - src1
120 | MULLW_MayOflo Reg Reg Reg
121 -- dst = 1 if src1 * src2 overflows
122 -- pseudo-instruction; pretty-printed as:
123 -- mullwo. dst, src1, src2
125 -- rlwinm dst, dst, 2, 31,31
127 | AND Reg Reg RI -- dst, src1, src2
128 | OR Reg Reg RI -- dst, src1, src2
129 | XOR Reg Reg RI -- dst, src1, src2
130 | XORIS Reg Reg Imm -- XOR Immediate Shifted dst, src1, src2
137 | SLW Reg Reg RI -- shift left word
138 | SRW Reg Reg RI -- shift right word
139 | SRAW Reg Reg RI -- shift right arithmetic word
141 -- Rotate Left Word Immediate then AND with Mask
142 | RLWINM Reg Reg Int Int Int
144 | FADD Size Reg Reg Reg
145 | FSUB Size Reg Reg Reg
146 | FMUL Size Reg Reg Reg
147 | FDIV Size Reg Reg Reg
148 | FNEG Reg Reg -- negate is the same for single and double prec.
152 | FCTIWZ Reg Reg -- convert to integer word
153 | FRSP Reg Reg -- reduce to single precision
154 -- (but destination is a FP register)
156 | CRNOR Int Int Int -- condition register nor
157 | MFCR Reg -- move from condition register
159 | MFLR Reg -- move from link register
160 | FETCHPC Reg -- pseudo-instruction:
161 -- bcl to next insn, mflr reg
163 | LWSYNC -- memory barrier
166 -- | Get the registers that are being used by this instruction.
167 -- regUsage doesn't need to do any trickery for jumps and such.
168 -- Just state precisely the regs read and written by that insn.
169 -- The consequences of control flow transfers, as far as register
170 -- allocation goes, are taken care of by the register allocator.
172 ppc_regUsageOfInstr :: Instr -> RegUsage
173 ppc_regUsageOfInstr instr
175 LD _ reg addr -> usage (regAddr addr, [reg])
176 LA _ reg addr -> usage (regAddr addr, [reg])
177 ST _ reg addr -> usage (reg : regAddr addr, [])
178 STU _ reg addr -> usage (reg : regAddr addr, [])
179 LIS reg _ -> usage ([], [reg])
180 LI reg _ -> usage ([], [reg])
181 MR reg1 reg2 -> usage ([reg2], [reg1])
182 CMP _ reg ri -> usage (reg : regRI ri,[])
183 CMPL _ reg ri -> usage (reg : regRI ri,[])
185 BCCFAR _ _ -> noUsage
186 MTCTR reg -> usage ([reg],[])
188 BL _ params -> usage (params, callClobberedRegs)
189 BCTRL params -> usage (params, callClobberedRegs)
190 ADD reg1 reg2 ri -> usage (reg2 : regRI ri, [reg1])
191 ADDC reg1 reg2 reg3-> usage ([reg2,reg3], [reg1])
192 ADDE reg1 reg2 reg3-> usage ([reg2,reg3], [reg1])
193 ADDIS reg1 reg2 _ -> usage ([reg2], [reg1])
194 SUBF reg1 reg2 reg3-> usage ([reg2,reg3], [reg1])
195 MULLW reg1 reg2 ri -> usage (reg2 : regRI ri, [reg1])
196 DIVW reg1 reg2 reg3-> usage ([reg2,reg3], [reg1])
197 DIVWU reg1 reg2 reg3-> usage ([reg2,reg3], [reg1])
198 MULLW_MayOflo reg1 reg2 reg3
199 -> usage ([reg2,reg3], [reg1])
200 AND reg1 reg2 ri -> usage (reg2 : regRI ri, [reg1])
201 OR reg1 reg2 ri -> usage (reg2 : regRI ri, [reg1])
202 XOR reg1 reg2 ri -> usage (reg2 : regRI ri, [reg1])
203 XORIS reg1 reg2 _ -> usage ([reg2], [reg1])
204 EXTS _ reg1 reg2 -> usage ([reg2], [reg1])
205 NEG reg1 reg2 -> usage ([reg2], [reg1])
206 NOT reg1 reg2 -> usage ([reg2], [reg1])
207 SLW reg1 reg2 ri -> usage (reg2 : regRI ri, [reg1])
208 SRW reg1 reg2 ri -> usage (reg2 : regRI ri, [reg1])
209 SRAW reg1 reg2 ri -> usage (reg2 : regRI ri, [reg1])
210 RLWINM reg1 reg2 _ _ _
211 -> usage ([reg2], [reg1])
212 FADD _ r1 r2 r3 -> usage ([r2,r3], [r1])
213 FSUB _ r1 r2 r3 -> usage ([r2,r3], [r1])
214 FMUL _ r1 r2 r3 -> usage ([r2,r3], [r1])
215 FDIV _ r1 r2 r3 -> usage ([r2,r3], [r1])
216 FNEG r1 r2 -> usage ([r2], [r1])
217 FCMP r1 r2 -> usage ([r1,r2], [])
218 FCTIWZ r1 r2 -> usage ([r2], [r1])
219 FRSP r1 r2 -> usage ([r2], [r1])
220 MFCR reg -> usage ([], [reg])
221 MFLR reg -> usage ([], [reg])
222 FETCHPC reg -> usage ([], [reg])
225 usage (src, dst) = RU (filter interesting src)
226 (filter interesting dst)
227 regAddr (AddrRegReg r1 r2) = [r1, r2]
228 regAddr (AddrRegImm r1 _) = [r1]
230 regRI (RIReg r) = [r]
233 interesting :: Reg -> Bool
234 interesting (RegVirtual _) = True
235 interesting (RegReal (RealRegSingle i))
236 = isFastTrue (freeReg i)
238 interesting (RegReal (RealRegPair{}))
239 = panic "PPC.Instr.interesting: no reg pairs on this arch"
243 -- | Apply a given mapping to all the register references in this
245 ppc_patchRegsOfInstr :: Instr -> (Reg -> Reg) -> Instr
246 ppc_patchRegsOfInstr instr env
248 LD sz reg addr -> LD sz (env reg) (fixAddr addr)
249 LA sz reg addr -> LA sz (env reg) (fixAddr addr)
250 ST sz reg addr -> ST sz (env reg) (fixAddr addr)
251 STU sz reg addr -> STU sz (env reg) (fixAddr addr)
252 LIS reg imm -> LIS (env reg) imm
253 LI reg imm -> LI (env reg) imm
254 MR reg1 reg2 -> MR (env reg1) (env reg2)
255 CMP sz reg ri -> CMP sz (env reg) (fixRI ri)
256 CMPL sz reg ri -> CMPL sz (env reg) (fixRI ri)
257 BCC cond lbl -> BCC cond lbl
258 BCCFAR cond lbl -> BCCFAR cond lbl
259 MTCTR reg -> MTCTR (env reg)
260 BCTR targets lbl -> BCTR targets lbl
261 BL imm argRegs -> BL imm argRegs -- argument regs
262 BCTRL argRegs -> BCTRL argRegs -- cannot be remapped
263 ADD reg1 reg2 ri -> ADD (env reg1) (env reg2) (fixRI ri)
264 ADDC reg1 reg2 reg3-> ADDC (env reg1) (env reg2) (env reg3)
265 ADDE reg1 reg2 reg3-> ADDE (env reg1) (env reg2) (env reg3)
266 ADDIS reg1 reg2 imm -> ADDIS (env reg1) (env reg2) imm
267 SUBF reg1 reg2 reg3-> SUBF (env reg1) (env reg2) (env reg3)
268 MULLW reg1 reg2 ri -> MULLW (env reg1) (env reg2) (fixRI ri)
269 DIVW reg1 reg2 reg3-> DIVW (env reg1) (env reg2) (env reg3)
270 DIVWU reg1 reg2 reg3-> DIVWU (env reg1) (env reg2) (env reg3)
271 MULLW_MayOflo reg1 reg2 reg3
272 -> MULLW_MayOflo (env reg1) (env reg2) (env reg3)
273 AND reg1 reg2 ri -> AND (env reg1) (env reg2) (fixRI ri)
274 OR reg1 reg2 ri -> OR (env reg1) (env reg2) (fixRI ri)
275 XOR reg1 reg2 ri -> XOR (env reg1) (env reg2) (fixRI ri)
276 XORIS reg1 reg2 imm -> XORIS (env reg1) (env reg2) imm
277 EXTS sz reg1 reg2 -> EXTS sz (env reg1) (env reg2)
278 NEG reg1 reg2 -> NEG (env reg1) (env reg2)
279 NOT reg1 reg2 -> NOT (env reg1) (env reg2)
280 SLW reg1 reg2 ri -> SLW (env reg1) (env reg2) (fixRI ri)
281 SRW reg1 reg2 ri -> SRW (env reg1) (env reg2) (fixRI ri)
282 SRAW reg1 reg2 ri -> SRAW (env reg1) (env reg2) (fixRI ri)
283 RLWINM reg1 reg2 sh mb me
284 -> RLWINM (env reg1) (env reg2) sh mb me
285 FADD sz r1 r2 r3 -> FADD sz (env r1) (env r2) (env r3)
286 FSUB sz r1 r2 r3 -> FSUB sz (env r1) (env r2) (env r3)
287 FMUL sz r1 r2 r3 -> FMUL sz (env r1) (env r2) (env r3)
288 FDIV sz r1 r2 r3 -> FDIV sz (env r1) (env r2) (env r3)
289 FNEG r1 r2 -> FNEG (env r1) (env r2)
290 FCMP r1 r2 -> FCMP (env r1) (env r2)
291 FCTIWZ r1 r2 -> FCTIWZ (env r1) (env r2)
292 FRSP r1 r2 -> FRSP (env r1) (env r2)
293 MFCR reg -> MFCR (env reg)
294 MFLR reg -> MFLR (env reg)
295 FETCHPC reg -> FETCHPC (env reg)
298 fixAddr (AddrRegReg r1 r2) = AddrRegReg (env r1) (env r2)
299 fixAddr (AddrRegImm r1 i) = AddrRegImm (env r1) i
301 fixRI (RIReg r) = RIReg (env r)
305 --------------------------------------------------------------------------------
306 -- | Checks whether this instruction is a jump/branch instruction.
307 -- One that can change the flow of control in a way that the
308 -- register allocator needs to worry about.
309 ppc_isJumpishInstr :: Instr -> Bool
310 ppc_isJumpishInstr instr
321 -- | Checks whether this instruction is a jump/branch instruction.
322 -- One that can change the flow of control in a way that the
323 -- register allocator needs to worry about.
324 ppc_jumpDestsOfInstr :: Instr -> [BlockId]
325 ppc_jumpDestsOfInstr insn
329 BCTR targets _ -> [id | Just id <- targets]
333 -- | Change the destination of this jump instruction.
334 -- Used in the linear allocator when adding fixup blocks for join
336 ppc_patchJumpInstr :: Instr -> (BlockId -> BlockId) -> Instr
337 ppc_patchJumpInstr insn patchF
339 BCC cc id -> BCC cc (patchF id)
340 BCCFAR cc id -> BCCFAR cc (patchF id)
341 BCTR ids lbl -> BCTR (map (fmap patchF) ids) lbl
345 -- -----------------------------------------------------------------------------
347 -- | An instruction to spill a register into a spill slot.
349 :: Reg -- register to spill
350 -> Int -- current stack delta
351 -> Int -- spill slot to use
354 ppc_mkSpillInstr reg delta slot
355 = let off = spillSlotToOffset slot
357 let sz = case targetClassOfReg reg of
360 _ -> panic "PPC.Instr.mkSpillInstr: no match"
361 in ST sz reg (AddrRegImm sp (ImmInt (off-delta)))
365 :: Reg -- register to load
366 -> Int -- current stack delta
367 -> Int -- spill slot to use
370 ppc_mkLoadInstr reg delta slot
371 = let off = spillSlotToOffset slot
373 let sz = case targetClassOfReg reg of
376 _ -> panic "PPC.Instr.mkLoadInstr: no match"
377 in LD sz reg (AddrRegImm sp (ImmInt (off-delta)))
384 maxSpillSlots = ((rESERVED_C_STACK_BYTES - 64) `div` spillSlotSize) - 1
386 -- convert a spill slot number to a *byte* offset, with no sign:
387 -- decide on a per arch basis whether you are spilling above or below
388 -- the C stack pointer.
389 spillSlotToOffset :: Int -> Int
390 spillSlotToOffset slot
391 | slot >= 0 && slot < maxSpillSlots
392 = 64 + spillSlotSize * slot
394 = pprPanic "spillSlotToOffset:"
395 ( text "invalid spill location: " <> int slot
396 $$ text "maxSpillSlots: " <> int maxSpillSlots)
399 --------------------------------------------------------------------------------
400 -- | See if this instruction is telling us the current C stack delta
405 ppc_takeDeltaInstr instr
415 ppc_isMetaInstr instr
424 -- | Copy the value in a register to another one.
425 -- Must work for all register classes.
426 ppc_mkRegRegMoveInstr
431 ppc_mkRegRegMoveInstr src dst
435 -- | Make an unconditional jump instruction.
436 -- For architectures with branch delay slots, its ok to put
437 -- a NOP after the jump. Don't fill the delay slot with an
438 -- instruction that references regs or you'll confuse the
448 -- | Take the source and destination from this reg -> reg move instruction
449 -- or Nothing if it's not one
450 ppc_takeRegRegMoveInstr :: Instr -> Maybe (Reg,Reg)
451 ppc_takeRegRegMoveInstr (MR dst src) = Just (src,dst)
452 ppc_takeRegRegMoveInstr _ = Nothing