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"
39 import List ( partition, sort )
42 import Stix ( DestInfo(..) )
43 import CLabel ( pprCLabel_asm, isAsmTemp, CLabel{-instance Ord-} )
44 import FiniteMap ( addToFM, lookupFM, FiniteMap )
46 import Constants ( rESERVED_C_STACK_BYTES )
47 import Unique ( Unique, Uniquable(..) )
50 %************************************************************************
52 \subsection{Sets of registers}
54 %************************************************************************
58 -- Blargh. Use ghc stuff soon! Or: perhaps that's not such a good
59 -- idea. Most of these sets are either empty or very small, and it
60 -- might be that the overheads of the FiniteMap based set implementation
61 -- is a net loss. The same might be true of FeSets.
63 newtype RegSet = MkRegSet [Reg]
66 = MkRegSet (nukeDups (sort xs))
67 where nukeDups :: [Reg] -> [Reg]
71 = if x == y then nukeDups (y:xys)
72 else x : nukeDups (y:xys)
74 regSetToList (MkRegSet xs) = xs
75 isEmptyRegSet (MkRegSet xs) = null xs
76 emptyRegSet = MkRegSet []
77 eqRegSets (MkRegSet xs1) (MkRegSet xs2) = xs1 == xs2
78 unitRegSet x = MkRegSet [x]
79 filterRegSet p (MkRegSet xs) = MkRegSet (filter p xs)
81 elemRegSet x (MkRegSet xs)
85 f (y:ys) | x == y = True
89 unionRegSets (MkRegSet xs1) (MkRegSet xs2)
90 = MkRegSet (f xs1 xs2)
95 | a < b = a : f as (b:bs)
96 | a > b = b : f (a:as) bs
97 | otherwise = a : f as bs
99 minusRegSets (MkRegSet xs1) (MkRegSet xs2)
100 = MkRegSet (f xs1 xs2)
105 | a < b = a : f as (b:bs)
106 | a > b = f (a:as) bs
107 | otherwise = f as bs
109 intersectionRegSets (MkRegSet xs1) (MkRegSet xs2)
110 = MkRegSet (f xs1 xs2)
115 | a < b = f as (b:bs)
116 | a > b = f (a:as) bs
117 | otherwise = a : f as bs
120 %************************************************************************
122 \subsection{@RegUsage@ type; @noUsage@, @endUsage@, @regUsage@ functions}
124 %************************************************************************
126 @regUsage@ returns the sets of src and destination registers used by a
127 particular instruction. Machine registers that are pre-allocated to
128 stgRegs are filtered out, because they are uninteresting from a
129 register allocation standpoint. (We wouldn't want them to end up on
130 the free list!) As far as we are concerned, the fixed registers
131 simply don't exist (for allocation purposes, anyway).
133 regUsage doesn't need to do any trickery for jumps and such. Just
134 state precisely the regs read and written by that insn. The
135 consequences of control flow transfers, as far as register allocation
136 goes, are taken care of by @insnFuture@.
139 data RegUsage = RU RegSet RegSet
142 noUsage = RU emptyRegSet emptyRegSet
144 regUsage :: Instr -> RegUsage
146 interesting (VirtualRegI _) = True
147 interesting (VirtualRegF _) = True
148 interesting (VirtualRegD _) = True
149 interesting (RealReg (I# i)) = _IS_TRUE_(freeReg i)
151 #if alpha_TARGET_ARCH
153 regUsage instr = case instr of
154 LD B reg addr -> usage (regAddr addr, [reg, t9])
155 LD BU reg addr -> usage (regAddr addr, [reg, t9])
156 -- LD W reg addr -> usage (regAddr addr, [reg, t9]) : UNUSED
157 -- LD WU reg addr -> usage (regAddr addr, [reg, t9]) : UNUSED
158 LD sz reg addr -> usage (regAddr addr, [reg])
159 LDA reg addr -> usage (regAddr addr, [reg])
160 LDAH reg addr -> usage (regAddr addr, [reg])
161 LDGP reg addr -> usage (regAddr addr, [reg])
162 LDI sz reg imm -> usage ([], [reg])
163 ST B reg addr -> usage (reg : regAddr addr, [t9, t10])
164 -- ST W reg addr -> usage (reg : regAddr addr, [t9, t10]) : UNUSED
165 ST sz reg addr -> usage (reg : regAddr addr, [])
166 CLR reg -> usage ([], [reg])
167 ABS sz ri reg -> usage (regRI ri, [reg])
168 NEG sz ov ri reg -> usage (regRI ri, [reg])
169 ADD sz ov r1 ar r2 -> usage (r1 : regRI ar, [r2])
170 SADD sz sc r1 ar r2 -> usage (r1 : regRI ar, [r2])
171 SUB sz ov r1 ar r2 -> usage (r1 : regRI ar, [r2])
172 SSUB sz sc r1 ar r2 -> usage (r1 : regRI ar, [r2])
173 MUL sz ov r1 ar r2 -> usage (r1 : regRI ar, [r2])
174 DIV sz un r1 ar r2 -> usage (r1 : regRI ar, [r2, t9, t10, t11, t12])
175 REM sz un r1 ar r2 -> usage (r1 : regRI ar, [r2, t9, t10, t11, t12])
176 NOT ri reg -> usage (regRI ri, [reg])
177 AND r1 ar r2 -> usage (r1 : regRI ar, [r2])
178 ANDNOT r1 ar r2 -> usage (r1 : regRI ar, [r2])
179 OR r1 ar r2 -> usage (r1 : regRI ar, [r2])
180 ORNOT r1 ar r2 -> usage (r1 : regRI ar, [r2])
181 XOR r1 ar r2 -> usage (r1 : regRI ar, [r2])
182 XORNOT r1 ar r2 -> usage (r1 : regRI ar, [r2])
183 SLL r1 ar r2 -> usage (r1 : regRI ar, [r2])
184 SRL r1 ar r2 -> usage (r1 : regRI ar, [r2])
185 SRA r1 ar r2 -> usage (r1 : regRI ar, [r2])
186 ZAP r1 ar r2 -> usage (r1 : regRI ar, [r2])
187 ZAPNOT r1 ar r2 -> usage (r1 : regRI ar, [r2])
188 CMP co r1 ar r2 -> usage (r1 : regRI ar, [r2])
189 FCLR reg -> usage ([], [reg])
190 FABS r1 r2 -> usage ([r1], [r2])
191 FNEG sz r1 r2 -> usage ([r1], [r2])
192 FADD sz r1 r2 r3 -> usage ([r1, r2], [r3])
193 FDIV sz r1 r2 r3 -> usage ([r1, r2], [r3])
194 FMUL sz r1 r2 r3 -> usage ([r1, r2], [r3])
195 FSUB sz r1 r2 r3 -> usage ([r1, r2], [r3])
196 CVTxy sz1 sz2 r1 r2 -> usage ([r1], [r2])
197 FCMP sz co r1 r2 r3 -> usage ([r1, r2], [r3])
198 FMOV r1 r2 -> usage ([r1], [r2])
201 -- We assume that all local jumps will be BI/BF/BR. JMP must be out-of-line.
202 BI cond reg lbl -> usage ([reg], [])
203 BF cond reg lbl -> usage ([reg], [])
204 JMP reg addr hint -> RU (mkRegSet (filter interesting (regAddr addr))) freeRegSet
206 BSR _ n -> RU (argRegSet n) callClobberedRegSet
207 JSR reg addr n -> RU (argRegSet n) callClobberedRegSet
212 usage (src, dst) = RU (mkRegSet (filter interesting src))
213 (mkRegSet (filter interesting dst))
215 interesting (FixedReg _) = False
218 regAddr (AddrReg r1) = [r1]
219 regAddr (AddrRegImm r1 _) = [r1]
220 regAddr (AddrImm _) = []
222 regRI (RIReg r) = [r]
225 #endif {- alpha_TARGET_ARCH -}
226 -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
229 regUsage instr = case instr of
230 MOV sz src dst -> usageRW src dst
231 MOVZxL sz src dst -> usageRW src dst
232 MOVSxL sz src dst -> usageRW src dst
233 LEA sz src dst -> usageRW src dst
234 ADD sz src dst -> usageRM src dst
235 SUB sz src dst -> usageRM src dst
236 IMUL sz src dst -> usageRM src dst
237 IDIV sz src -> mkRU (eax:edx:use_R src) [eax,edx]
238 AND sz src dst -> usageRM src dst
239 OR sz src dst -> usageRM src dst
240 XOR sz src dst -> usageRM src dst
241 NOT sz op -> usageM op
242 NEGI sz op -> usageM op
243 SHL sz imm dst -> usageM dst
244 SAR sz imm dst -> usageM dst
245 SHR sz imm dst -> usageM dst
246 BT sz imm src -> mkRU (use_R src) []
248 PUSH sz op -> mkRU (use_R op) []
249 POP sz op -> mkRU [] (def_W op)
250 TEST sz src dst -> mkRU (use_R src ++ use_R dst) []
251 CMP sz src dst -> mkRU (use_R src ++ use_R dst) []
252 SETCC cond op -> mkRU [] (def_W op)
253 JXX cond lbl -> mkRU [] []
254 JMP dsts op -> mkRU (use_R op) []
255 CALL imm -> mkRU [] callClobberedRegs
256 CLTD -> mkRU [eax] [edx]
259 GMOV src dst -> mkRU [src] [dst]
260 GLD sz src dst -> mkRU (use_EA src) [dst]
261 GST sz src dst -> mkRU (src : use_EA dst) []
263 GLDZ dst -> mkRU [] [dst]
264 GLD1 dst -> mkRU [] [dst]
266 GFTOD src dst -> mkRU [src] [dst]
267 GFTOI src dst -> mkRU [src] [dst]
269 GDTOF src dst -> mkRU [src] [dst]
270 GDTOI src dst -> mkRU [src] [dst]
272 GITOF src dst -> mkRU [src] [dst]
273 GITOD src dst -> mkRU [src] [dst]
275 GADD sz s1 s2 dst -> mkRU [s1,s2] [dst]
276 GSUB sz s1 s2 dst -> mkRU [s1,s2] [dst]
277 GMUL sz s1 s2 dst -> mkRU [s1,s2] [dst]
278 GDIV sz s1 s2 dst -> mkRU [s1,s2] [dst]
280 GCMP sz src1 src2 -> mkRU [src1,src2] []
281 GABS sz src dst -> mkRU [src] [dst]
282 GNEG sz src dst -> mkRU [src] [dst]
283 GSQRT sz src dst -> mkRU [src] [dst]
284 GSIN sz src dst -> mkRU [src] [dst]
285 GCOS sz src dst -> mkRU [src] [dst]
286 GTAN sz src dst -> mkRU [src] [dst]
294 _ -> pprPanic "regUsage(x86)" empty
297 -- 2 operand form; first operand Read; second Written
298 usageRW :: Operand -> Operand -> RegUsage
299 usageRW op (OpReg reg) = mkRU (use_R op) [reg]
300 usageRW op (OpAddr ea) = mkRU (use_R op ++ use_EA ea) []
302 -- 2 operand form; first operand Read; second Modified
303 usageRM :: Operand -> Operand -> RegUsage
304 usageRM op (OpReg reg) = mkRU (use_R op ++ [reg]) [reg]
305 usageRM op (OpAddr ea) = mkRU (use_R op ++ use_EA ea) []
307 -- 1 operand form; operand Modified
308 usageM :: Operand -> RegUsage
309 usageM (OpReg reg) = mkRU [reg] [reg]
310 usageM (OpAddr ea) = mkRU (use_EA ea) []
312 -- Registers defd when an operand is written.
313 def_W (OpReg reg) = [reg]
314 def_W (OpAddr ea) = []
316 -- Registers used when an operand is read.
317 use_R (OpReg reg) = [reg]
318 use_R (OpImm imm) = []
319 use_R (OpAddr ea) = use_EA ea
321 -- Registers used to compute an effective address.
322 use_EA (ImmAddr _ _) = []
323 use_EA (AddrBaseIndex Nothing Nothing _) = []
324 use_EA (AddrBaseIndex (Just b) Nothing _) = [b]
325 use_EA (AddrBaseIndex Nothing (Just (i,_)) _) = [i]
326 use_EA (AddrBaseIndex (Just b) (Just (i,_)) _) = [b,i]
328 mkRU src dst = RU (regSetFromList (filter interesting src))
329 (regSetFromList (filter interesting dst))
331 -- Allow the spiller to de\cide whether or not it can use
332 -- %edx as a spill temporary.
339 #endif {- i386_TARGET_ARCH -}
340 -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
341 #if sparc_TARGET_ARCH
343 regUsage instr = case instr of
344 LD sz addr reg -> usage (regAddr addr, [reg])
345 ST sz reg addr -> usage (reg : regAddr addr, [])
346 ADD x cc r1 ar r2 -> usage (r1 : regRI ar, [r2])
347 SUB x cc r1 ar r2 -> usage (r1 : regRI ar, [r2])
348 AND b r1 ar r2 -> usage (r1 : regRI ar, [r2])
349 ANDN b r1 ar r2 -> usage (r1 : regRI ar, [r2])
350 OR b r1 ar r2 -> usage (r1 : regRI ar, [r2])
351 ORN b r1 ar r2 -> usage (r1 : regRI ar, [r2])
352 XOR b r1 ar r2 -> usage (r1 : regRI ar, [r2])
353 XNOR b r1 ar r2 -> usage (r1 : regRI ar, [r2])
354 SLL r1 ar r2 -> usage (r1 : regRI ar, [r2])
355 SRL r1 ar r2 -> usage (r1 : regRI ar, [r2])
356 SRA r1 ar r2 -> usage (r1 : regRI ar, [r2])
357 SETHI imm reg -> usage ([], [reg])
358 FABS s r1 r2 -> usage ([r1], [r2])
359 FADD s r1 r2 r3 -> usage ([r1, r2], [r3])
360 FCMP e s r1 r2 -> usage ([r1, r2], [])
361 FDIV s r1 r2 r3 -> usage ([r1, r2], [r3])
362 FMOV s r1 r2 -> usage ([r1], [r2])
363 FMUL s r1 r2 r3 -> usage ([r1, r2], [r3])
364 FNEG s r1 r2 -> usage ([r1], [r2])
365 FSQRT s r1 r2 -> usage ([r1], [r2])
366 FSUB s r1 r2 r3 -> usage ([r1, r2], [r3])
367 FxTOy s1 s2 r1 r2 -> usage ([r1], [r2])
369 -- We assume that all local jumps will be BI/BF. JMP must be out-of-line.
370 JMP dst addr -> usage (regAddr addr, [])
372 CALL _ n True -> noUsage
373 CALL _ n False -> usage (argRegs n, callClobberedRegs)
377 usage (src, dst) = RU (regSetFromList (filter interesting src))
378 (regSetFromList (filter interesting dst))
380 regAddr (AddrRegReg r1 r2) = [r1, r2]
381 regAddr (AddrRegImm r1 _) = [r1]
383 regRI (RIReg r) = [r]
386 #endif {- sparc_TARGET_ARCH -}
390 %************************************************************************
392 \subsection{Free, reserved, call-clobbered, and argument registers}
394 %************************************************************************
396 @freeRegs@ is the list of registers we can use in register allocation.
397 @freeReg@ (below) says if a particular register is free.
399 With a per-instruction clobber list, we might be able to get some of
400 these back, but it's probably not worth the hassle.
402 @callClobberedRegs@ ... the obvious.
404 @argRegs@: assuming a call with N arguments, what registers will be
405 used to hold arguments? (NB: it doesn't know whether the arguments
406 are integer or floating-point...)
408 findReservedRegs tells us which regs can be used as spill temporaries.
409 The list of instructions for which we are attempting allocation is
410 supplied. This is so that we can (at least for x86) examine it to
411 discover which registers are being used in a fixed way -- for example,
412 %eax and %edx are used by integer division, so they can't be used as
413 spill temporaries. However, most instruction lists don't do integer
414 division, so we don't want to rule them out altogether.
416 findReservedRegs returns not a list of spill temporaries, but a list
417 of list of them. This is so that the allocator can attempt allocating
418 with at first no spill temps, then if that fails, increasing numbers.
419 For x86 it is important that we minimise the number of regs reserved
420 as spill temporaries, since there are so few. For Alpha and Sparc
421 this isn't a concern; we just ignore the supplied code list and return
422 a singleton list which we know will satisfy all spill demands.
425 findReservedRegs :: [Instr] -> [[Reg]]
426 findReservedRegs instrs
427 #if alpha_TARGET_ARCH
428 = --[[NCG_Reserved_I1, NCG_Reserved_I2,
429 -- NCG_Reserved_F1, NCG_Reserved_F2]]
430 error "findReservedRegs: alpha"
432 #if sparc_TARGET_ARCH
433 = [[NCG_SpillTmp_I1, NCG_SpillTmp_I2,
434 NCG_SpillTmp_D1, NCG_SpillTmp_D2,
435 NCG_SpillTmp_F1, NCG_SpillTmp_F2]]
438 -- We can use %fake4 and %fake5 safely for float temps.
439 -- Int regs are more troublesome. Only %ecx is definitely
440 -- available. If there are no division insns, we can use %edx
441 -- too. At a pinch, we also could bag %eax if there are no
442 -- divisions and no ccalls, but so far we've never encountered
443 -- a situation where three integer temporaries are necessary.
445 -- Because registers are in short supply on x86, we give the
446 -- allocator a whole bunch of possibilities, starting with zero
447 -- temporaries and working up to all that are available. This
448 -- is inefficient, but spills are pretty rare, so we don't care
449 -- if the register allocator has to try half a dozen or so possibilities
450 -- before getting to one that works.
454 = ecx : if any hasFixedEDX instrs then [] else [edx]
456 = case intregs_avail of
457 [i1] -> [ [], [i1], [f1], [i1,f1], [f1,f2],
460 [i1,i2] -> [ [], [i1], [f1], [i1,i2], [i1,f1], [f1,f2],
461 [i1,i2,f1], [i1,f1,f2], [i1,i2,f1,f2] ]
467 %************************************************************************
469 \subsection{@InsnFuture@ type; @insnFuture@ function}
471 %************************************************************************
473 @insnFuture@ indicates the places we could get to following the
474 current instruction. This is used by the register allocator to
475 compute the flow edges between instructions.
479 = NoFuture -- makes a non-local jump; for the purposes of
480 -- register allocation, it exits our domain
481 | Next -- falls through to next insn
482 | Branch CLabel -- unconditional branch to the label
483 | NextOrBranch CLabel -- conditional branch to the label
484 | MultiFuture [CLabel] -- multiple specific futures
486 --instance Outputable InsnFuture where
487 -- ppr NoFuture = text "NoFuture"
488 -- ppr Next = text "Next"
489 -- ppr (Branch clbl) = text "(Branch " <> ppr clbl <> char ')'
490 -- ppr (NextOrBranch clbl) = text "(NextOrBranch " <> ppr clbl <> char ')'
496 #if alpha_TARGET_ARCH
498 -- We assume that all local jumps will be BI/BF. JMP must be out-of-line.
500 BR (ImmCLbl lbl) -> RL (lookup lbl) future
501 BI _ _ (ImmCLbl lbl) -> RL (lookup lbl `unionRegSets` live) future
502 BF _ _ (ImmCLbl lbl) -> RL (lookup lbl `unionRegSets` live) future
503 JMP _ _ _ -> RL emptyRegSet future
504 BSR _ _ -> RL live future
505 JSR _ _ _ -> RL live future
506 LABEL lbl -> RL live (FL (all `unionRegSets` live) (addToFM env lbl live))
509 #endif {- alpha_TARGET_ARCH -}
510 -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
514 JXX _ clbl | isAsmTemp clbl -> NextOrBranch clbl
515 JXX _ _ -> panic "insnFuture: conditional jump to non-local label"
517 -- If the insn says what its dests are, use em!
518 JMP (DestInfo dsts) _ -> MultiFuture dsts
520 -- unconditional jump to local label
521 JMP NoDestInfo (OpImm (ImmCLbl clbl)) | isAsmTemp clbl -> Branch clbl
523 -- unconditional jump to non-local label
524 JMP NoDestInfo lbl -> NoFuture
527 JMP _ _ -> panic "insnFuture(x86): JMP wierdness"
531 #endif {- i386_TARGET_ARCH -}
532 -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
533 #if sparc_TARGET_ARCH
535 -- We assume that all local jumps will be BI/BF.
536 BI ALWAYS _ (ImmCLbl clbl) -> Branch clbl
537 BI other _ (ImmCLbl clbl) -> NextOrBranch clbl
538 BI other _ _ -> panic "nativeGen(sparc):insnFuture(BI)"
540 BF ALWAYS _ (ImmCLbl clbl) -> Branch clbl
541 BF other _ (ImmCLbl clbl) -> NextOrBranch clbl
542 BF other _ _ -> panic "nativeGen(sparc):insnFuture(BF)"
544 -- CALL(terminal) must be out-of-line. JMP is not out-of-line
545 -- iff it specifies its destinations.
546 JMP NoDestInfo _ -> NoFuture -- n.b. NoFuture == MultiFuture []
547 JMP (DestInfo dsts) _ -> MultiFuture dsts
549 CALL _ _ True -> NoFuture
553 #endif {- sparc_TARGET_ARCH -}
556 %************************************************************************
558 \subsection{@patchRegs@ function}
560 %************************************************************************
562 @patchRegs@ takes an instruction (possibly with
563 MemoryReg/UnmappedReg registers) and changes all register references
564 according to the supplied environment.
567 patchRegs :: Instr -> (Reg -> Reg) -> Instr
569 #if alpha_TARGET_ARCH
571 patchRegs instr env = case instr of
572 LD sz reg addr -> LD sz (env reg) (fixAddr addr)
573 LDA reg addr -> LDA (env reg) (fixAddr addr)
574 LDAH reg addr -> LDAH (env reg) (fixAddr addr)
575 LDGP reg addr -> LDGP (env reg) (fixAddr addr)
576 LDI sz reg imm -> LDI sz (env reg) imm
577 ST sz reg addr -> ST sz (env reg) (fixAddr addr)
578 CLR reg -> CLR (env reg)
579 ABS sz ar reg -> ABS sz (fixRI ar) (env reg)
580 NEG sz ov ar reg -> NEG sz ov (fixRI ar) (env reg)
581 ADD sz ov r1 ar r2 -> ADD sz ov (env r1) (fixRI ar) (env r2)
582 SADD sz sc r1 ar r2 -> SADD sz sc (env r1) (fixRI ar) (env r2)
583 SUB sz ov r1 ar r2 -> SUB sz ov (env r1) (fixRI ar) (env r2)
584 SSUB sz sc r1 ar r2 -> SSUB sz sc (env r1) (fixRI ar) (env r2)
585 MUL sz ov r1 ar r2 -> MUL sz ov (env r1) (fixRI ar) (env r2)
586 DIV sz un r1 ar r2 -> DIV sz un (env r1) (fixRI ar) (env r2)
587 REM sz un r1 ar r2 -> REM sz un (env r1) (fixRI ar) (env r2)
588 NOT ar reg -> NOT (fixRI ar) (env reg)
589 AND r1 ar r2 -> AND (env r1) (fixRI ar) (env r2)
590 ANDNOT r1 ar r2 -> ANDNOT (env r1) (fixRI ar) (env r2)
591 OR r1 ar r2 -> OR (env r1) (fixRI ar) (env r2)
592 ORNOT r1 ar r2 -> ORNOT (env r1) (fixRI ar) (env r2)
593 XOR r1 ar r2 -> XOR (env r1) (fixRI ar) (env r2)
594 XORNOT r1 ar r2 -> XORNOT (env r1) (fixRI ar) (env r2)
595 SLL r1 ar r2 -> SLL (env r1) (fixRI ar) (env r2)
596 SRL r1 ar r2 -> SRL (env r1) (fixRI ar) (env r2)
597 SRA r1 ar r2 -> SRA (env r1) (fixRI ar) (env r2)
598 ZAP r1 ar r2 -> ZAP (env r1) (fixRI ar) (env r2)
599 ZAPNOT r1 ar r2 -> ZAPNOT (env r1) (fixRI ar) (env r2)
600 CMP co r1 ar r2 -> CMP co (env r1) (fixRI ar) (env r2)
601 FCLR reg -> FCLR (env reg)
602 FABS r1 r2 -> FABS (env r1) (env r2)
603 FNEG s r1 r2 -> FNEG s (env r1) (env r2)
604 FADD s r1 r2 r3 -> FADD s (env r1) (env r2) (env r3)
605 FDIV s r1 r2 r3 -> FDIV s (env r1) (env r2) (env r3)
606 FMUL s r1 r2 r3 -> FMUL s (env r1) (env r2) (env r3)
607 FSUB s r1 r2 r3 -> FSUB s (env r1) (env r2) (env r3)
608 CVTxy s1 s2 r1 r2 -> CVTxy s1 s2 (env r1) (env r2)
609 FCMP s co r1 r2 r3 -> FCMP s co (env r1) (env r2) (env r3)
610 FMOV r1 r2 -> FMOV (env r1) (env r2)
611 BI cond reg lbl -> BI cond (env reg) lbl
612 BF cond reg lbl -> BF cond (env reg) lbl
613 JMP reg addr hint -> JMP (env reg) (fixAddr addr) hint
614 JSR reg addr i -> JSR (env reg) (fixAddr addr) i
617 fixAddr (AddrReg r1) = AddrReg (env r1)
618 fixAddr (AddrRegImm r1 i) = AddrRegImm (env r1) i
619 fixAddr other = other
621 fixRI (RIReg r) = RIReg (env r)
624 #endif {- alpha_TARGET_ARCH -}
625 -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
628 patchRegs instr env = case instr of
629 MOV sz src dst -> patch2 (MOV sz) src dst
630 MOVZxL sz src dst -> patch2 (MOVZxL sz) src dst
631 MOVSxL sz src dst -> patch2 (MOVSxL sz) src dst
632 LEA sz src dst -> patch2 (LEA sz) src dst
633 ADD sz src dst -> patch2 (ADD sz) src dst
634 SUB sz src dst -> patch2 (SUB sz) src dst
635 IMUL sz src dst -> patch2 (IMUL sz) src dst
636 IDIV sz src -> patch1 (IDIV sz) src
637 AND sz src dst -> patch2 (AND sz) src dst
638 OR sz src dst -> patch2 (OR sz) src dst
639 XOR sz src dst -> patch2 (XOR sz) src dst
640 NOT sz op -> patch1 (NOT sz) op
641 NEGI sz op -> patch1 (NEGI sz) op
642 SHL sz imm dst -> patch1 (SHL sz imm) dst
643 SAR sz imm dst -> patch1 (SAR sz imm) dst
644 SHR sz imm dst -> patch1 (SHR sz imm) dst
645 BT sz imm src -> patch1 (BT sz imm) src
646 TEST sz src dst -> patch2 (TEST sz) src dst
647 CMP sz src dst -> patch2 (CMP sz) src dst
648 PUSH sz op -> patch1 (PUSH sz) op
649 POP sz op -> patch1 (POP sz) op
650 SETCC cond op -> patch1 (SETCC cond) op
651 JMP dsts op -> patch1 (JMP dsts) op
653 GMOV src dst -> GMOV (env src) (env dst)
654 GLD sz src dst -> GLD sz (lookupAddr src) (env dst)
655 GST sz src dst -> GST sz (env src) (lookupAddr dst)
657 GLDZ dst -> GLDZ (env dst)
658 GLD1 dst -> GLD1 (env dst)
660 GFTOD src dst -> GFTOD (env src) (env dst)
661 GFTOI src dst -> GFTOI (env src) (env dst)
663 GDTOF src dst -> GDTOF (env src) (env dst)
664 GDTOI src dst -> GDTOI (env src) (env dst)
666 GITOF src dst -> GITOF (env src) (env dst)
667 GITOD src dst -> GITOD (env src) (env dst)
669 GADD sz s1 s2 dst -> GADD sz (env s1) (env s2) (env dst)
670 GSUB sz s1 s2 dst -> GSUB sz (env s1) (env s2) (env dst)
671 GMUL sz s1 s2 dst -> GMUL sz (env s1) (env s2) (env dst)
672 GDIV sz s1 s2 dst -> GDIV sz (env s1) (env s2) (env dst)
674 GCMP sz src1 src2 -> GCMP sz (env src1) (env src2)
675 GABS sz src dst -> GABS sz (env src) (env dst)
676 GNEG sz src dst -> GNEG sz (env src) (env dst)
677 GSQRT sz src dst -> GSQRT sz (env src) (env dst)
678 GSIN sz src dst -> GSIN sz (env src) (env dst)
679 GCOS sz src dst -> GCOS sz (env src) (env dst)
680 GTAN sz src dst -> GTAN sz (env src) (env dst)
691 _ -> pprPanic "patchInstr(x86)" empty
694 patch1 insn op = insn (patchOp op)
695 patch2 insn src dst = insn (patchOp src) (patchOp dst)
697 patchOp (OpReg reg) = OpReg (env reg)
698 patchOp (OpImm imm) = OpImm imm
699 patchOp (OpAddr ea) = OpAddr (lookupAddr ea)
701 lookupAddr (ImmAddr imm off) = ImmAddr imm off
702 lookupAddr (AddrBaseIndex base index disp)
703 = AddrBaseIndex (lookupBase base) (lookupIndex index) disp
705 lookupBase Nothing = Nothing
706 lookupBase (Just r) = Just (env r)
708 lookupIndex Nothing = Nothing
709 lookupIndex (Just (r,i)) = Just (env r, i)
711 #endif {- i386_TARGET_ARCH -}
712 -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
713 #if sparc_TARGET_ARCH
715 patchRegs instr env = case instr of
716 LD sz addr reg -> LD sz (fixAddr addr) (env reg)
717 ST sz reg addr -> ST sz (env reg) (fixAddr addr)
718 ADD x cc r1 ar r2 -> ADD x cc (env r1) (fixRI ar) (env r2)
719 SUB x cc r1 ar r2 -> SUB x cc (env r1) (fixRI ar) (env r2)
720 AND b r1 ar r2 -> AND b (env r1) (fixRI ar) (env r2)
721 ANDN b r1 ar r2 -> ANDN b (env r1) (fixRI ar) (env r2)
722 OR b r1 ar r2 -> OR b (env r1) (fixRI ar) (env r2)
723 ORN b r1 ar r2 -> ORN b (env r1) (fixRI ar) (env r2)
724 XOR b r1 ar r2 -> XOR b (env r1) (fixRI ar) (env r2)
725 XNOR b r1 ar r2 -> XNOR b (env r1) (fixRI ar) (env r2)
726 SLL r1 ar r2 -> SLL (env r1) (fixRI ar) (env r2)
727 SRL r1 ar r2 -> SRL (env r1) (fixRI ar) (env r2)
728 SRA r1 ar r2 -> SRA (env r1) (fixRI ar) (env r2)
729 SETHI imm reg -> SETHI imm (env reg)
730 FABS s r1 r2 -> FABS s (env r1) (env r2)
731 FADD s r1 r2 r3 -> FADD s (env r1) (env r2) (env r3)
732 FCMP e s r1 r2 -> FCMP e s (env r1) (env r2)
733 FDIV s r1 r2 r3 -> FDIV s (env r1) (env r2) (env r3)
734 FMOV s r1 r2 -> FMOV s (env r1) (env r2)
735 FMUL s r1 r2 r3 -> FMUL s (env r1) (env r2) (env r3)
736 FNEG s r1 r2 -> FNEG s (env r1) (env r2)
737 FSQRT s r1 r2 -> FSQRT s (env r1) (env r2)
738 FSUB s r1 r2 r3 -> FSUB s (env r1) (env r2) (env r3)
739 FxTOy s1 s2 r1 r2 -> FxTOy s1 s2 (env r1) (env r2)
740 JMP dsts addr -> JMP dsts (fixAddr addr)
743 fixAddr (AddrRegReg r1 r2) = AddrRegReg (env r1) (env r2)
744 fixAddr (AddrRegImm r1 i) = AddrRegImm (env r1) i
746 fixRI (RIReg r) = RIReg (env r)
749 #endif {- sparc_TARGET_ARCH -}
752 %************************************************************************
754 \subsection{@spillReg@ and @loadReg@ functions}
756 %************************************************************************
758 Spill to memory, and load it back...
760 JRS, 000122: on x86, don't spill directly above the stack pointer,
761 since some insn sequences (int <-> conversions, and eventually
762 StixInteger) use this as a temp location. Leave 8 words (ie, 64 bytes
763 for a 64-bit arch) of slop.
767 spillSlotSize = IF_ARCH_alpha( 8, IF_ARCH_sparc( 8, IF_ARCH_i386( 12, )))
770 maxSpillSlots = ((rESERVED_C_STACK_BYTES - 64) `div` spillSlotSize) - 1
772 -- convert a spill slot number to a *byte* offset, with no sign:
773 -- decide on a per arch basis whether you are spilling above or below
774 -- the C stack pointer.
775 spillSlotToOffset :: Int -> Int
776 spillSlotToOffset slot
777 | slot >= 0 && slot < maxSpillSlots
778 = 64 + spillSlotSize * slot
780 = pprPanic "spillSlotToOffset:"
781 (text "invalid spill location: " <> int slot)
783 vregToSpillSlot :: FiniteMap Unique Int -> Unique -> Int
784 vregToSpillSlot vreg_to_slot_map u
785 = case lookupFM vreg_to_slot_map u of
787 Nothing -> pprPanic "vregToSpillSlot: unmapped vreg" (ppr u)
790 spillReg, loadReg :: FiniteMap Unique Int -> Int -> Reg -> Reg -> Instr
792 spillReg vreg_to_slot_map delta dyn vreg
794 = let slot_no = vregToSpillSlot vreg_to_slot_map (getUnique vreg)
795 off = spillSlotToOffset slot_no
797 {-Alpha: spill below the stack pointer (?)-}
798 IF_ARCH_alpha( ST sz dyn (spRel (- (off `div` 8)))
800 {-I386: spill above stack pointer leaving 3 words/spill-}
801 ,IF_ARCH_i386 ( let off_w = (off-delta) `div` 4
802 in case regClass vreg of
803 RcInteger -> MOV L (OpReg dyn) (OpAddr (spRel off_w))
804 _ -> GST F80 dyn (spRel off_w) -- RcFloat/RcDouble
806 {-SPARC: spill below frame pointer leaving 2 words/spill-}
808 let off_w = 1 + (off `div` 4)
809 sz = case regClass vreg of
813 in ST sz dyn (fpRel (- off_w))
817 loadReg vreg_to_slot_map delta vreg dyn
819 = let slot_no = vregToSpillSlot vreg_to_slot_map (getUnique vreg)
820 off = spillSlotToOffset slot_no
822 IF_ARCH_alpha( LD sz dyn (spRel (- (off `div` 8)))
824 ,IF_ARCH_i386 ( let off_w = (off-delta) `div` 4
825 in case regClass vreg of
826 RcInteger -> MOV L (OpAddr (spRel off_w)) (OpReg dyn)
827 _ -> GLD F80 (spRel off_w) dyn -- RcFloat/RcDouble
830 let off_w = 1 + (off `div` 4)
831 sz = case regClass vreg of
835 in LD sz (fpRel (- off_w)) dyn