2 % (c) The AQUA Project, Glasgow University, 1996-1998
4 \section[RegAllocInfo]{Machine-specific info used for register allocation}
6 The (machine-independent) allocator itself is in @AsmRegAlloc@.
9 #include "nativeGen/NCG.h"
37 #include "HsVersions.h"
42 import Stix ( DestInfo(..) )
43 import CLabel ( isAsmTemp, CLabel{-instance Ord-} )
44 import FiniteMap ( addToFM, lookupFM, FiniteMap )
46 import Constants ( rESERVED_C_STACK_BYTES )
47 import Unique ( Unique, Uniquable(..) )
52 %************************************************************************
54 \subsection{Sets of registers}
56 %************************************************************************
60 -- Blargh. Use ghc stuff soon! Or: perhaps that's not such a good
61 -- idea. Most of these sets are either empty or very small, and it
62 -- might be that the overheads of the FiniteMap based set implementation
63 -- is a net loss. The same might be true of FeSets.
65 newtype RegSet = MkRegSet [Reg]
68 = MkRegSet (nukeDups (sort xs))
69 where nukeDups :: [Reg] -> [Reg]
73 = if x == y then nukeDups (y:xys)
74 else x : nukeDups (y:xys)
76 regSetToList (MkRegSet xs) = xs
77 isEmptyRegSet (MkRegSet xs) = null xs
78 emptyRegSet = MkRegSet []
79 eqRegSets (MkRegSet xs1) (MkRegSet xs2) = xs1 == xs2
80 unitRegSet x = MkRegSet [x]
81 filterRegSet p (MkRegSet xs) = MkRegSet (filter p xs)
83 elemRegSet x (MkRegSet xs)
87 f (y:ys) | x == y = True
91 unionRegSets (MkRegSet xs1) (MkRegSet xs2)
92 = MkRegSet (f xs1 xs2)
97 | a < b = a : f as (b:bs)
98 | a > b = b : f (a:as) bs
99 | otherwise = a : f as bs
101 minusRegSets (MkRegSet xs1) (MkRegSet xs2)
102 = MkRegSet (f xs1 xs2)
107 | a < b = a : f as (b:bs)
108 | a > b = f (a:as) bs
109 | otherwise = f as bs
111 intersectionRegSets (MkRegSet xs1) (MkRegSet xs2)
112 = MkRegSet (f xs1 xs2)
117 | a < b = f as (b:bs)
118 | a > b = f (a:as) bs
119 | otherwise = a : f as bs
122 %************************************************************************
124 \subsection{@RegUsage@ type; @noUsage@, @endUsage@, @regUsage@ functions}
126 %************************************************************************
128 @regUsage@ returns the sets of src and destination registers used by a
129 particular instruction. Machine registers that are pre-allocated to
130 stgRegs are filtered out, because they are uninteresting from a
131 register allocation standpoint. (We wouldn't want them to end up on
132 the free list!) As far as we are concerned, the fixed registers
133 simply don't exist (for allocation purposes, anyway).
135 regUsage doesn't need to do any trickery for jumps and such. Just
136 state precisely the regs read and written by that insn. The
137 consequences of control flow transfers, as far as register allocation
138 goes, are taken care of by @insnFuture@.
141 data RegUsage = RU RegSet RegSet
144 noUsage = RU emptyRegSet emptyRegSet
146 regUsage :: Instr -> RegUsage
148 interesting (VirtualRegI _) = True
149 interesting (VirtualRegF _) = True
150 interesting (VirtualRegD _) = True
151 interesting (RealReg i) = isFastTrue (freeReg i)
153 #if alpha_TARGET_ARCH
155 regUsage instr = case instr of
156 LD B reg addr -> usage (regAddr addr, [reg, t9])
157 LD BU reg addr -> usage (regAddr addr, [reg, t9])
158 -- LD W reg addr -> usage (regAddr addr, [reg, t9]) : UNUSED
159 -- LD WU reg addr -> usage (regAddr addr, [reg, t9]) : UNUSED
160 LD sz reg addr -> usage (regAddr addr, [reg])
161 LDA reg addr -> usage (regAddr addr, [reg])
162 LDAH reg addr -> usage (regAddr addr, [reg])
163 LDGP reg addr -> usage (regAddr addr, [reg])
164 LDI sz reg imm -> usage ([], [reg])
165 ST B reg addr -> usage (reg : regAddr addr, [t9, t10])
166 -- ST W reg addr -> usage (reg : regAddr addr, [t9, t10]) : UNUSED
167 ST sz reg addr -> usage (reg : regAddr addr, [])
168 CLR reg -> usage ([], [reg])
169 ABS sz ri reg -> usage (regRI ri, [reg])
170 NEG sz ov ri reg -> usage (regRI ri, [reg])
171 ADD sz ov r1 ar r2 -> usage (r1 : regRI ar, [r2])
172 SADD sz sc r1 ar r2 -> usage (r1 : regRI ar, [r2])
173 SUB sz ov r1 ar r2 -> usage (r1 : regRI ar, [r2])
174 SSUB sz sc r1 ar r2 -> usage (r1 : regRI ar, [r2])
175 MUL sz ov r1 ar r2 -> usage (r1 : regRI ar, [r2])
176 DIV sz un r1 ar r2 -> usage (r1 : regRI ar, [r2, t9, t10, t11, t12])
177 REM sz un r1 ar r2 -> usage (r1 : regRI ar, [r2, t9, t10, t11, t12])
178 NOT ri reg -> usage (regRI ri, [reg])
179 AND r1 ar r2 -> usage (r1 : regRI ar, [r2])
180 ANDNOT r1 ar r2 -> usage (r1 : regRI ar, [r2])
181 OR r1 ar r2 -> usage (r1 : regRI ar, [r2])
182 ORNOT r1 ar r2 -> usage (r1 : regRI ar, [r2])
183 XOR r1 ar r2 -> usage (r1 : regRI ar, [r2])
184 XORNOT 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 ZAP r1 ar r2 -> usage (r1 : regRI ar, [r2])
189 ZAPNOT r1 ar r2 -> usage (r1 : regRI ar, [r2])
190 CMP co r1 ar r2 -> usage (r1 : regRI ar, [r2])
191 FCLR reg -> usage ([], [reg])
192 FABS r1 r2 -> usage ([r1], [r2])
193 FNEG sz r1 r2 -> usage ([r1], [r2])
194 FADD sz r1 r2 r3 -> usage ([r1, r2], [r3])
195 FDIV sz r1 r2 r3 -> usage ([r1, r2], [r3])
196 FMUL sz r1 r2 r3 -> usage ([r1, r2], [r3])
197 FSUB sz r1 r2 r3 -> usage ([r1, r2], [r3])
198 CVTxy sz1 sz2 r1 r2 -> usage ([r1], [r2])
199 FCMP sz co r1 r2 r3 -> usage ([r1, r2], [r3])
200 FMOV r1 r2 -> usage ([r1], [r2])
203 -- We assume that all local jumps will be BI/BF/BR. JMP must be out-of-line.
204 BI cond reg lbl -> usage ([reg], [])
205 BF cond reg lbl -> usage ([reg], [])
206 JMP reg addr hint -> RU (mkRegSet (filter interesting (regAddr addr))) freeRegSet
208 BSR _ n -> RU (argRegSet n) callClobberedRegSet
209 JSR reg addr n -> RU (argRegSet n) callClobberedRegSet
214 usage (src, dst) = RU (mkRegSet (filter interesting src))
215 (mkRegSet (filter interesting dst))
217 interesting (FixedReg _) = False
220 regAddr (AddrReg r1) = [r1]
221 regAddr (AddrRegImm r1 _) = [r1]
222 regAddr (AddrImm _) = []
224 regRI (RIReg r) = [r]
227 #endif {- alpha_TARGET_ARCH -}
228 -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
231 regUsage instr = case instr of
232 MOV sz src dst -> usageRW src dst
233 MOVZxL sz src dst -> usageRW src dst
234 MOVSxL sz src dst -> usageRW src dst
235 LEA sz src dst -> usageRW src dst
236 ADD sz src dst -> usageRM src dst
237 SUB sz src dst -> usageRM src dst
238 IMUL sz src dst -> usageRM src dst
239 IQUOT sz src dst -> usageRM src dst
240 IREM sz src dst -> usageRM src dst
241 AND sz src dst -> usageRM src dst
242 OR sz src dst -> usageRM src dst
243 XOR sz src dst -> usageRM src dst
244 NOT sz op -> usageM op
245 NEGI sz op -> usageM op
246 SHL sz imm dst -> usageM dst
247 SAR sz imm dst -> usageM dst
248 SHR sz imm dst -> usageM dst
249 BT sz imm src -> mkRU (use_R src) []
251 PUSH sz op -> mkRU (use_R op) []
252 POP sz op -> mkRU [] (def_W op)
253 TEST sz src dst -> mkRU (use_R src ++ use_R dst) []
254 CMP sz src dst -> mkRU (use_R src ++ use_R dst) []
255 SETCC cond op -> mkRU [] (def_W op)
256 JXX cond lbl -> mkRU [] []
257 JMP dsts op -> mkRU (use_R op) []
258 CALL imm -> mkRU [] callClobberedRegs
259 CLTD -> mkRU [eax] [edx]
262 GMOV src dst -> mkRU [src] [dst]
263 GLD sz src dst -> mkRU (use_EA src) [dst]
264 GST sz src dst -> mkRU (src : use_EA dst) []
266 GLDZ dst -> mkRU [] [dst]
267 GLD1 dst -> mkRU [] [dst]
269 GFTOD src dst -> mkRU [src] [dst]
270 GFTOI src dst -> mkRU [src] [dst]
272 GDTOF src dst -> mkRU [src] [dst]
273 GDTOI src dst -> mkRU [src] [dst]
275 GITOF src dst -> mkRU [src] [dst]
276 GITOD src dst -> mkRU [src] [dst]
278 GADD sz s1 s2 dst -> mkRU [s1,s2] [dst]
279 GSUB sz s1 s2 dst -> mkRU [s1,s2] [dst]
280 GMUL sz s1 s2 dst -> mkRU [s1,s2] [dst]
281 GDIV sz s1 s2 dst -> mkRU [s1,s2] [dst]
283 GCMP sz src1 src2 -> mkRU [src1,src2] []
284 GABS sz src dst -> mkRU [src] [dst]
285 GNEG sz src dst -> mkRU [src] [dst]
286 GSQRT sz src dst -> mkRU [src] [dst]
287 GSIN sz src dst -> mkRU [src] [dst]
288 GCOS sz src dst -> mkRU [src] [dst]
289 GTAN sz src dst -> mkRU [src] [dst]
297 _ -> pprPanic "regUsage(x86)" empty
300 -- 2 operand form; first operand Read; second Written
301 usageRW :: Operand -> Operand -> RegUsage
302 usageRW op (OpReg reg) = mkRU (use_R op) [reg]
303 usageRW op (OpAddr ea) = mkRU (use_R op ++ use_EA ea) []
305 -- 2 operand form; first operand Read; second Modified
306 usageRM :: Operand -> Operand -> RegUsage
307 usageRM op (OpReg reg) = mkRU (use_R op ++ [reg]) [reg]
308 usageRM op (OpAddr ea) = mkRU (use_R op ++ use_EA ea) []
310 -- 1 operand form; operand Modified
311 usageM :: Operand -> RegUsage
312 usageM (OpReg reg) = mkRU [reg] [reg]
313 usageM (OpAddr ea) = mkRU (use_EA ea) []
315 -- Registers defd when an operand is written.
316 def_W (OpReg reg) = [reg]
317 def_W (OpAddr ea) = []
319 -- Registers used when an operand is read.
320 use_R (OpReg reg) = [reg]
321 use_R (OpImm imm) = []
322 use_R (OpAddr ea) = use_EA ea
324 -- Registers used to compute an effective address.
325 use_EA (ImmAddr _ _) = []
326 use_EA (AddrBaseIndex Nothing Nothing _) = []
327 use_EA (AddrBaseIndex (Just b) Nothing _) = [b]
328 use_EA (AddrBaseIndex Nothing (Just (i,_)) _) = [i]
329 use_EA (AddrBaseIndex (Just b) (Just (i,_)) _) = [b,i]
331 mkRU src dst = RU (regSetFromList (filter interesting src))
332 (regSetFromList (filter interesting dst))
334 #endif {- i386_TARGET_ARCH -}
335 -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
336 #if sparc_TARGET_ARCH
338 regUsage instr = case instr of
339 LD sz addr reg -> usage (regAddr addr, [reg])
340 ST sz reg addr -> usage (reg : regAddr addr, [])
341 ADD x cc r1 ar r2 -> usage (r1 : regRI ar, [r2])
342 SUB x cc r1 ar r2 -> usage (r1 : regRI ar, [r2])
343 AND b r1 ar r2 -> usage (r1 : regRI ar, [r2])
344 ANDN b r1 ar r2 -> usage (r1 : regRI ar, [r2])
345 OR b r1 ar r2 -> usage (r1 : regRI ar, [r2])
346 ORN b r1 ar r2 -> usage (r1 : regRI ar, [r2])
347 XOR b r1 ar r2 -> usage (r1 : regRI ar, [r2])
348 XNOR b r1 ar r2 -> usage (r1 : regRI ar, [r2])
349 SLL r1 ar r2 -> usage (r1 : regRI ar, [r2])
350 SRL r1 ar r2 -> usage (r1 : regRI ar, [r2])
351 SRA r1 ar r2 -> usage (r1 : regRI ar, [r2])
352 SETHI imm reg -> usage ([], [reg])
353 FABS s r1 r2 -> usage ([r1], [r2])
354 FADD s r1 r2 r3 -> usage ([r1, r2], [r3])
355 FCMP e s r1 r2 -> usage ([r1, r2], [])
356 FDIV s r1 r2 r3 -> usage ([r1, r2], [r3])
357 FMOV s r1 r2 -> usage ([r1], [r2])
358 FMUL s r1 r2 r3 -> usage ([r1, r2], [r3])
359 FNEG s r1 r2 -> usage ([r1], [r2])
360 FSQRT s r1 r2 -> usage ([r1], [r2])
361 FSUB s r1 r2 r3 -> usage ([r1, r2], [r3])
362 FxTOy s1 s2 r1 r2 -> usage ([r1], [r2])
364 -- We assume that all local jumps will be BI/BF. JMP must be out-of-line.
365 JMP dst addr -> usage (regAddr addr, [])
367 CALL _ n True -> noUsage
368 CALL _ n False -> usage (argRegs n, callClobberedRegs)
372 usage (src, dst) = RU (regSetFromList (filter interesting src))
373 (regSetFromList (filter interesting dst))
375 regAddr (AddrRegReg r1 r2) = [r1, r2]
376 regAddr (AddrRegImm r1 _) = [r1]
378 regRI (RIReg r) = [r]
381 #endif {- sparc_TARGET_ARCH -}
385 %************************************************************************
387 \subsection{Free, reserved, call-clobbered, and argument registers}
389 %************************************************************************
391 @freeRegs@ is the list of registers we can use in register allocation.
392 @freeReg@ (below) says if a particular register is free.
394 With a per-instruction clobber list, we might be able to get some of
395 these back, but it's probably not worth the hassle.
397 @callClobberedRegs@ ... the obvious.
399 @argRegs@: assuming a call with N arguments, what registers will be
400 used to hold arguments? (NB: it doesn't know whether the arguments
401 are integer or floating-point...)
403 findReservedRegs tells us which regs can be used as spill temporaries.
404 The list of instructions for which we are attempting allocation is
405 supplied. This is so that we can (at least for x86) examine it to
406 discover which registers are being used in a fixed way -- for example,
407 %eax and %edx are used by integer division, so they can't be used as
408 spill temporaries. However, most instruction lists don't do integer
409 division, so we don't want to rule them out altogether.
411 findReservedRegs returns not a list of spill temporaries, but a list
412 of list of them. This is so that the allocator can attempt allocating
413 with at first no spill temps, then if that fails, increasing numbers.
414 For x86 it is important that we minimise the number of regs reserved
415 as spill temporaries, since there are so few. For Alpha and Sparc
416 this isn't a concern; we just ignore the supplied code list and return
417 a singleton list which we know will satisfy all spill demands.
420 findReservedRegs :: [Instr] -> [[Reg]]
421 findReservedRegs instrs
422 #if alpha_TARGET_ARCH
423 = --[[NCG_Reserved_I1, NCG_Reserved_I2,
424 -- NCG_Reserved_F1, NCG_Reserved_F2]]
425 error "findReservedRegs: alpha"
427 #if sparc_TARGET_ARCH
428 = [[NCG_SpillTmp_I1, NCG_SpillTmp_I2,
429 NCG_SpillTmp_D1, NCG_SpillTmp_D2,
430 NCG_SpillTmp_F1, NCG_SpillTmp_F2]]
433 -- We can use %fake4 and %fake5 safely for float temps.
434 -- Int regs are more troublesome. Only %ecx and %edx are
435 -- definitely. At a pinch, we also could bag %eax if there
436 -- are no ccalls, but so far we've never encountered
437 -- a situation where three integer temporaries are necessary.
439 -- Because registers are in short supply on x86, we give the
440 -- allocator a whole bunch of possibilities, starting with zero
441 -- temporaries and working up to all that are available. This
442 -- is inefficient, but spills are pretty rare, so we don't care
443 -- if the register allocator has to try half a dozen or so possibilities
444 -- before getting to one that works.
450 = case intregs_avail of
451 [i1] -> [ [], [i1], [f1], [i1,f1], [f1,f2],
454 [i1,i2] -> [ [], [i1], [f1], [i1,i2], [i1,f1], [f1,f2],
455 [i1,i2,f1], [i1,f1,f2], [i1,i2,f1,f2] ]
461 %************************************************************************
463 \subsection{@InsnFuture@ type; @insnFuture@ function}
465 %************************************************************************
467 @insnFuture@ indicates the places we could get to following the
468 current instruction. This is used by the register allocator to
469 compute the flow edges between instructions.
473 = NoFuture -- makes a non-local jump; for the purposes of
474 -- register allocation, it exits our domain
475 | Next -- falls through to next insn
476 | Branch CLabel -- unconditional branch to the label
477 | NextOrBranch CLabel -- conditional branch to the label
478 | MultiFuture [CLabel] -- multiple specific futures
480 --instance Outputable InsnFuture where
481 -- ppr NoFuture = text "NoFuture"
482 -- ppr Next = text "Next"
483 -- ppr (Branch clbl) = text "(Branch " <> ppr clbl <> char ')'
484 -- ppr (NextOrBranch clbl) = text "(NextOrBranch " <> ppr clbl <> char ')'
490 #if alpha_TARGET_ARCH
492 -- We assume that all local jumps will be BI/BF. JMP must be out-of-line.
494 BR (ImmCLbl lbl) -> RL (lookup lbl) future
495 BI _ _ (ImmCLbl lbl) -> RL (lookup lbl `unionRegSets` live) future
496 BF _ _ (ImmCLbl lbl) -> RL (lookup lbl `unionRegSets` live) future
497 JMP _ _ _ -> RL emptyRegSet future
498 BSR _ _ -> RL live future
499 JSR _ _ _ -> RL live future
500 LABEL lbl -> RL live (FL (all `unionRegSets` live) (addToFM env lbl live))
503 #endif {- alpha_TARGET_ARCH -}
504 -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
508 JXX _ clbl | isAsmTemp clbl -> NextOrBranch clbl
509 JXX _ _ -> panic "insnFuture: conditional jump to non-local label"
511 -- If the insn says what its dests are, use em!
512 JMP (DestInfo dsts) _ -> MultiFuture dsts
514 -- unconditional jump to local label
515 JMP NoDestInfo (OpImm (ImmCLbl clbl)) | isAsmTemp clbl -> Branch clbl
517 -- unconditional jump to non-local label
518 JMP NoDestInfo lbl -> NoFuture
521 JMP _ _ -> panic "insnFuture(x86): JMP wierdness"
525 #endif {- i386_TARGET_ARCH -}
526 -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
527 #if sparc_TARGET_ARCH
529 -- We assume that all local jumps will be BI/BF.
530 BI ALWAYS _ (ImmCLbl clbl) -> Branch clbl
531 BI other _ (ImmCLbl clbl) -> NextOrBranch clbl
532 BI other _ _ -> panic "nativeGen(sparc):insnFuture(BI)"
534 BF ALWAYS _ (ImmCLbl clbl) -> Branch clbl
535 BF other _ (ImmCLbl clbl) -> NextOrBranch clbl
536 BF other _ _ -> panic "nativeGen(sparc):insnFuture(BF)"
538 -- CALL(terminal) must be out-of-line. JMP is not out-of-line
539 -- iff it specifies its destinations.
540 JMP NoDestInfo _ -> NoFuture -- n.b. NoFuture == MultiFuture []
541 JMP (DestInfo dsts) _ -> MultiFuture dsts
543 CALL _ _ True -> NoFuture
547 #endif {- sparc_TARGET_ARCH -}
550 %************************************************************************
552 \subsection{@patchRegs@ function}
554 %************************************************************************
556 @patchRegs@ takes an instruction (possibly with
557 MemoryReg/UnmappedReg registers) and changes all register references
558 according to the supplied environment.
561 patchRegs :: Instr -> (Reg -> Reg) -> Instr
563 #if alpha_TARGET_ARCH
565 patchRegs instr env = case instr of
566 LD sz reg addr -> LD sz (env reg) (fixAddr addr)
567 LDA reg addr -> LDA (env reg) (fixAddr addr)
568 LDAH reg addr -> LDAH (env reg) (fixAddr addr)
569 LDGP reg addr -> LDGP (env reg) (fixAddr addr)
570 LDI sz reg imm -> LDI sz (env reg) imm
571 ST sz reg addr -> ST sz (env reg) (fixAddr addr)
572 CLR reg -> CLR (env reg)
573 ABS sz ar reg -> ABS sz (fixRI ar) (env reg)
574 NEG sz ov ar reg -> NEG sz ov (fixRI ar) (env reg)
575 ADD sz ov r1 ar r2 -> ADD sz ov (env r1) (fixRI ar) (env r2)
576 SADD sz sc r1 ar r2 -> SADD sz sc (env r1) (fixRI ar) (env r2)
577 SUB sz ov r1 ar r2 -> SUB sz ov (env r1) (fixRI ar) (env r2)
578 SSUB sz sc r1 ar r2 -> SSUB sz sc (env r1) (fixRI ar) (env r2)
579 MUL sz ov r1 ar r2 -> MUL sz ov (env r1) (fixRI ar) (env r2)
580 DIV sz un r1 ar r2 -> DIV sz un (env r1) (fixRI ar) (env r2)
581 REM sz un r1 ar r2 -> REM sz un (env r1) (fixRI ar) (env r2)
582 NOT ar reg -> NOT (fixRI ar) (env reg)
583 AND r1 ar r2 -> AND (env r1) (fixRI ar) (env r2)
584 ANDNOT r1 ar r2 -> ANDNOT (env r1) (fixRI ar) (env r2)
585 OR r1 ar r2 -> OR (env r1) (fixRI ar) (env r2)
586 ORNOT r1 ar r2 -> ORNOT (env r1) (fixRI ar) (env r2)
587 XOR r1 ar r2 -> XOR (env r1) (fixRI ar) (env r2)
588 XORNOT r1 ar r2 -> XORNOT (env r1) (fixRI ar) (env r2)
589 SLL r1 ar r2 -> SLL (env r1) (fixRI ar) (env r2)
590 SRL r1 ar r2 -> SRL (env r1) (fixRI ar) (env r2)
591 SRA r1 ar r2 -> SRA (env r1) (fixRI ar) (env r2)
592 ZAP r1 ar r2 -> ZAP (env r1) (fixRI ar) (env r2)
593 ZAPNOT r1 ar r2 -> ZAPNOT (env r1) (fixRI ar) (env r2)
594 CMP co r1 ar r2 -> CMP co (env r1) (fixRI ar) (env r2)
595 FCLR reg -> FCLR (env reg)
596 FABS r1 r2 -> FABS (env r1) (env r2)
597 FNEG s r1 r2 -> FNEG s (env r1) (env r2)
598 FADD s r1 r2 r3 -> FADD s (env r1) (env r2) (env r3)
599 FDIV s r1 r2 r3 -> FDIV s (env r1) (env r2) (env r3)
600 FMUL s r1 r2 r3 -> FMUL s (env r1) (env r2) (env r3)
601 FSUB s r1 r2 r3 -> FSUB s (env r1) (env r2) (env r3)
602 CVTxy s1 s2 r1 r2 -> CVTxy s1 s2 (env r1) (env r2)
603 FCMP s co r1 r2 r3 -> FCMP s co (env r1) (env r2) (env r3)
604 FMOV r1 r2 -> FMOV (env r1) (env r2)
605 BI cond reg lbl -> BI cond (env reg) lbl
606 BF cond reg lbl -> BF cond (env reg) lbl
607 JMP reg addr hint -> JMP (env reg) (fixAddr addr) hint
608 JSR reg addr i -> JSR (env reg) (fixAddr addr) i
611 fixAddr (AddrReg r1) = AddrReg (env r1)
612 fixAddr (AddrRegImm r1 i) = AddrRegImm (env r1) i
613 fixAddr other = other
615 fixRI (RIReg r) = RIReg (env r)
618 #endif {- alpha_TARGET_ARCH -}
619 -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
622 patchRegs instr env = case instr of
623 MOV sz src dst -> patch2 (MOV sz) src dst
624 MOVZxL sz src dst -> patch2 (MOVZxL sz) src dst
625 MOVSxL sz src dst -> patch2 (MOVSxL sz) src dst
626 LEA sz src dst -> patch2 (LEA sz) src dst
627 ADD sz src dst -> patch2 (ADD sz) src dst
628 SUB sz src dst -> patch2 (SUB sz) src dst
629 IMUL sz src dst -> patch2 (IMUL sz) src dst
630 IQUOT sz src dst -> patch2 (IQUOT sz) src dst
631 IREM sz src dst -> patch2 (IREM sz) src dst
632 AND sz src dst -> patch2 (AND sz) src dst
633 OR sz src dst -> patch2 (OR sz) src dst
634 XOR sz src dst -> patch2 (XOR sz) src dst
635 NOT sz op -> patch1 (NOT sz) op
636 NEGI sz op -> patch1 (NEGI sz) op
637 SHL sz imm dst -> patch1 (SHL sz imm) dst
638 SAR sz imm dst -> patch1 (SAR sz imm) dst
639 SHR sz imm dst -> patch1 (SHR sz imm) dst
640 BT sz imm src -> patch1 (BT sz imm) src
641 TEST sz src dst -> patch2 (TEST sz) src dst
642 CMP sz src dst -> patch2 (CMP sz) src dst
643 PUSH sz op -> patch1 (PUSH sz) op
644 POP sz op -> patch1 (POP sz) op
645 SETCC cond op -> patch1 (SETCC cond) op
646 JMP dsts op -> patch1 (JMP dsts) op
648 GMOV src dst -> GMOV (env src) (env dst)
649 GLD sz src dst -> GLD sz (lookupAddr src) (env dst)
650 GST sz src dst -> GST sz (env src) (lookupAddr dst)
652 GLDZ dst -> GLDZ (env dst)
653 GLD1 dst -> GLD1 (env dst)
655 GFTOD src dst -> GFTOD (env src) (env dst)
656 GFTOI src dst -> GFTOI (env src) (env dst)
658 GDTOF src dst -> GDTOF (env src) (env dst)
659 GDTOI src dst -> GDTOI (env src) (env dst)
661 GITOF src dst -> GITOF (env src) (env dst)
662 GITOD src dst -> GITOD (env src) (env dst)
664 GADD sz s1 s2 dst -> GADD sz (env s1) (env s2) (env dst)
665 GSUB sz s1 s2 dst -> GSUB sz (env s1) (env s2) (env dst)
666 GMUL sz s1 s2 dst -> GMUL sz (env s1) (env s2) (env dst)
667 GDIV sz s1 s2 dst -> GDIV sz (env s1) (env s2) (env dst)
669 GCMP sz src1 src2 -> GCMP sz (env src1) (env src2)
670 GABS sz src dst -> GABS sz (env src) (env dst)
671 GNEG sz src dst -> GNEG sz (env src) (env dst)
672 GSQRT sz src dst -> GSQRT sz (env src) (env dst)
673 GSIN sz src dst -> GSIN sz (env src) (env dst)
674 GCOS sz src dst -> GCOS sz (env src) (env dst)
675 GTAN sz src dst -> GTAN sz (env src) (env dst)
686 _ -> pprPanic "patchInstr(x86)" empty
689 patch1 insn op = insn (patchOp op)
690 patch2 insn src dst = insn (patchOp src) (patchOp dst)
692 patchOp (OpReg reg) = OpReg (env reg)
693 patchOp (OpImm imm) = OpImm imm
694 patchOp (OpAddr ea) = OpAddr (lookupAddr ea)
696 lookupAddr (ImmAddr imm off) = ImmAddr imm off
697 lookupAddr (AddrBaseIndex base index disp)
698 = AddrBaseIndex (lookupBase base) (lookupIndex index) disp
700 lookupBase Nothing = Nothing
701 lookupBase (Just r) = Just (env r)
703 lookupIndex Nothing = Nothing
704 lookupIndex (Just (r,i)) = Just (env r, i)
706 #endif {- i386_TARGET_ARCH -}
707 -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
708 #if sparc_TARGET_ARCH
710 patchRegs instr env = case instr of
711 LD sz addr reg -> LD sz (fixAddr addr) (env reg)
712 ST sz reg addr -> ST sz (env reg) (fixAddr addr)
713 ADD x cc r1 ar r2 -> ADD x cc (env r1) (fixRI ar) (env r2)
714 SUB x cc r1 ar r2 -> SUB x cc (env r1) (fixRI ar) (env r2)
715 AND b r1 ar r2 -> AND b (env r1) (fixRI ar) (env r2)
716 ANDN b r1 ar r2 -> ANDN b (env r1) (fixRI ar) (env r2)
717 OR b r1 ar r2 -> OR b (env r1) (fixRI ar) (env r2)
718 ORN b r1 ar r2 -> ORN b (env r1) (fixRI ar) (env r2)
719 XOR b r1 ar r2 -> XOR b (env r1) (fixRI ar) (env r2)
720 XNOR b r1 ar r2 -> XNOR b (env r1) (fixRI ar) (env r2)
721 SLL r1 ar r2 -> SLL (env r1) (fixRI ar) (env r2)
722 SRL r1 ar r2 -> SRL (env r1) (fixRI ar) (env r2)
723 SRA r1 ar r2 -> SRA (env r1) (fixRI ar) (env r2)
724 SETHI imm reg -> SETHI imm (env reg)
725 FABS s r1 r2 -> FABS s (env r1) (env r2)
726 FADD s r1 r2 r3 -> FADD s (env r1) (env r2) (env r3)
727 FCMP e s r1 r2 -> FCMP e s (env r1) (env r2)
728 FDIV s r1 r2 r3 -> FDIV s (env r1) (env r2) (env r3)
729 FMOV s r1 r2 -> FMOV s (env r1) (env r2)
730 FMUL s r1 r2 r3 -> FMUL s (env r1) (env r2) (env r3)
731 FNEG s r1 r2 -> FNEG s (env r1) (env r2)
732 FSQRT s r1 r2 -> FSQRT s (env r1) (env r2)
733 FSUB s r1 r2 r3 -> FSUB s (env r1) (env r2) (env r3)
734 FxTOy s1 s2 r1 r2 -> FxTOy s1 s2 (env r1) (env r2)
735 JMP dsts addr -> JMP dsts (fixAddr addr)
738 fixAddr (AddrRegReg r1 r2) = AddrRegReg (env r1) (env r2)
739 fixAddr (AddrRegImm r1 i) = AddrRegImm (env r1) i
741 fixRI (RIReg r) = RIReg (env r)
744 #endif {- sparc_TARGET_ARCH -}
747 %************************************************************************
749 \subsection{@spillReg@ and @loadReg@ functions}
751 %************************************************************************
753 Spill to memory, and load it back...
755 JRS, 000122: on x86, don't spill directly above the stack pointer,
756 since some insn sequences (int <-> conversions, and eventually
757 StixInteger) use this as a temp location. Leave 8 words (ie, 64 bytes
758 for a 64-bit arch) of slop.
762 spillSlotSize = IF_ARCH_alpha( 8, IF_ARCH_sparc( 8, IF_ARCH_i386( 12, )))
765 maxSpillSlots = ((rESERVED_C_STACK_BYTES - 64) `div` spillSlotSize) - 1
767 -- convert a spill slot number to a *byte* offset, with no sign:
768 -- decide on a per arch basis whether you are spilling above or below
769 -- the C stack pointer.
770 spillSlotToOffset :: Int -> Int
771 spillSlotToOffset slot
772 | slot >= 0 && slot < maxSpillSlots
773 = 64 + spillSlotSize * slot
775 = pprPanic "spillSlotToOffset:"
776 (text "invalid spill location: " <> int slot)
778 vregToSpillSlot :: FiniteMap Unique Int -> Unique -> Int
779 vregToSpillSlot vreg_to_slot_map u
780 = case lookupFM vreg_to_slot_map u of
782 Nothing -> pprPanic "vregToSpillSlot: unmapped vreg" (ppr u)
785 spillReg, loadReg :: FiniteMap Unique Int -> Int -> Reg -> Reg -> Instr
787 spillReg vreg_to_slot_map delta dyn vreg
789 = let slot_no = vregToSpillSlot vreg_to_slot_map (getUnique vreg)
790 off = spillSlotToOffset slot_no
792 {-Alpha: spill below the stack pointer (?)-}
793 IF_ARCH_alpha( ST sz dyn (spRel (- (off `div` 8)))
795 {-I386: spill above stack pointer leaving 3 words/spill-}
796 ,IF_ARCH_i386 ( let off_w = (off-delta) `div` 4
797 in case regClass vreg of
798 RcInteger -> MOV L (OpReg dyn) (OpAddr (spRel off_w))
799 _ -> GST F80 dyn (spRel off_w) -- RcFloat/RcDouble
801 {-SPARC: spill below frame pointer leaving 2 words/spill-}
803 let off_w = 1 + (off `div` 4)
804 sz = case regClass vreg of
808 in ST sz dyn (fpRel (- off_w))
812 loadReg vreg_to_slot_map delta vreg dyn
814 = let slot_no = vregToSpillSlot vreg_to_slot_map (getUnique vreg)
815 off = spillSlotToOffset slot_no
817 IF_ARCH_alpha( LD sz dyn (spRel (- (off `div` 8)))
819 ,IF_ARCH_i386 ( let off_w = (off-delta) `div` 4
820 in case regClass vreg of
821 RcInteger -> MOV L (OpAddr (spRel off_w)) (OpReg dyn)
822 _ -> GLD F80 (spRel off_w) dyn -- RcFloat/RcDouble
825 let off_w = 1 + (off `div` 4)
826 sz = case regClass vreg of
830 in LD sz (fpRel (- off_w)) dyn