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"
38 IF_ARCH_i386(findReservedRegs COMMA,)
54 #include "HsVersions.h"
56 import List ( partition )
59 import MachCode ( InstrList )
61 import BitSet ( unitBS, mkBS, minusBS, unionBS, listBS, BitSet )
62 import CLabel ( pprCLabel_asm, CLabel{-instance Ord-} )
63 import FiniteMap ( addToFM, lookupFM, FiniteMap )
64 import OrdList ( mkUnitList )
65 import PrimRep ( PrimRep(..) )
66 import UniqSet -- quite a bit of it
70 %************************************************************************
72 \subsection{Register allocation information}
74 %************************************************************************
77 type RegSet = UniqSet Reg
79 mkRegSet :: [Reg] -> RegSet
81 unionRegSets, minusRegSet :: RegSet -> RegSet -> RegSet
82 elementOfRegSet :: Reg -> RegSet -> Bool
83 isEmptyRegSet :: RegSet -> Bool
84 regSetToList :: RegSet -> [Reg]
87 emptyRegSet = emptyUniqSet
88 unionRegSets = unionUniqSets
89 minusRegSet = minusUniqSet
90 elementOfRegSet = elementOfUniqSet
91 isEmptyRegSet = isEmptyUniqSet
92 regSetToList = uniqSetToList
94 freeRegSet, callClobberedRegSet :: RegSet
95 argRegSet :: Int -> RegSet
97 freeRegSet = mkRegSet freeRegs
98 callClobberedRegSet = mkRegSet callClobberedRegs
99 argRegSet n = mkRegSet (argRegs n)
101 type RegAssignment = FiniteMap Reg Reg
102 type RegConflicts = FiniteMap Int RegSet
104 data FutureLive = FL RegSet (FiniteMap CLabel RegSet)
114 = RF RegSet -- in use
119 = RI RegSet -- in use
121 RegSet -- destinations
126 %************************************************************************
128 \subsection{Register allocation information}
130 %************************************************************************
132 COMMENT ON THE EXTRA BitSet FOR SPARC MRegsState: Getting the conflicts
133 right is a bit tedious for doubles. We'd have to add a conflict
134 function to the MachineRegisters class, and we'd have to put a PrimRep
135 in the MappedReg datatype, or use some kludge (e.g. register 64 + n is
136 really the same as 32 + n, except that it's used for a double, so it
137 also conflicts with 33 + n) to deal with it. It's just not worth the
138 bother, so we just partition the free floating point registers into
139 two sets: one for single precision and one for double precision. We
140 never seem to run out of floating point registers anyway.
144 = MRs BitSet -- integer registers
145 BitSet -- floating-point registers
146 IF_ARCH_sparc(BitSet,) -- double registers handled separately
150 #if alpha_TARGET_ARCH
151 # define INT_FLPT_CUTOFF 32
154 # define INT_FLPT_CUTOFF 8
156 #if sparc_TARGET_ARCH
157 # define INT_FLPT_CUTOFF 32
158 # define SNGL_DBL_CUTOFF 48
161 mkMRegsState :: [RegNo] -> MRegsState
162 possibleMRegs :: PrimRep -> MRegsState -> [RegNo]
163 useMReg :: MRegsState -> FAST_REG_NO -> MRegsState
164 useMRegs :: MRegsState -> [RegNo] -> MRegsState
165 freeMReg :: MRegsState -> FAST_REG_NO -> MRegsState
166 freeMRegs :: MRegsState -> [RegNo] -> MRegsState
169 = MRs (mkBS is) (mkBS fs2) IF_ARCH_sparc((mkBS ds2),)
171 (is, fs) = partition (< INT_FLPT_CUTOFF) xs
172 #if sparc_TARGET_ARCH
173 (ss, ds) = partition (< SNGL_DBL_CUTOFF) fs
174 fs2 = map (subtract INT_FLPT_CUTOFF) ss
175 ds2 = map (subtract INT_FLPT_CUTOFF) (filter even ds)
177 fs2 = map (subtract INT_FLPT_CUTOFF) fs
180 ------------------------------------------------
181 #if sparc_TARGET_ARCH
182 possibleMRegs FloatRep (MRs _ ss _) = [ x + INT_FLPT_CUTOFF | x <- listBS ss]
183 possibleMRegs DoubleRep (MRs _ _ ds) = [ x + INT_FLPT_CUTOFF | x <- listBS ds]
184 possibleMRegs _ (MRs is _ _) = listBS is
186 possibleMRegs FloatRep (MRs _ fs) = [ x + INT_FLPT_CUTOFF | x <- listBS fs]
187 possibleMRegs DoubleRep (MRs _ fs) = [ x + INT_FLPT_CUTOFF | x <- listBS fs]
188 possibleMRegs _ (MRs is _) = listBS is
191 ------------------------------------------------
192 #if sparc_TARGET_ARCH
193 useMReg (MRs is ss ds) n
194 = if (n _LT_ ILIT(INT_FLPT_CUTOFF)) then
195 MRs (is `minusBS` unitBS IBOX(n)) ss ds
196 else if (n _LT_ ILIT(SNGL_DBL_CUTOFF)) then
197 MRs is (ss `minusBS` unitBS (IBOX(n _SUB_ ILIT(INT_FLPT_CUTOFF)))) ds
199 MRs is ss (ds `minusBS` unitBS (IBOX(n _SUB_ ILIT(INT_FLPT_CUTOFF))))
201 useMReg (MRs is fs) n
202 = if (n _LT_ ILIT(INT_FLPT_CUTOFF))
203 then MRs (is `minusBS` unitBS IBOX(n)) fs
204 else MRs is (fs `minusBS` unitBS (IBOX(n _SUB_ ILIT(INT_FLPT_CUTOFF))))
207 ------------------------------------------------
208 #if sparc_TARGET_ARCH
209 useMRegs (MRs is ss ds) xs
210 = MRs (is `minusBS` is2) (ss `minusBS` ss2) (ds `minusBS` ds2)
212 MRs is2 ss2 ds2 = mkMRegsState xs
214 useMRegs (MRs is fs) xs
215 = MRs (is `minusBS` is2) (fs `minusBS` fs2)
217 MRs is2 fs2 = mkMRegsState xs
220 ------------------------------------------------
221 #if sparc_TARGET_ARCH
222 freeMReg (MRs is ss ds) n
223 = if (n _LT_ ILIT(INT_FLPT_CUTOFF)) then
224 MRs (is `unionBS` unitBS IBOX(n)) ss ds
225 else if (n _LT_ ILIT(SNGL_DBL_CUTOFF)) then
226 MRs is (ss `unionBS` unitBS (IBOX(n _SUB_ ILIT(INT_FLPT_CUTOFF)))) ds
228 MRs is ss (ds `unionBS` unitBS (IBOX(n _SUB_ ILIT(INT_FLPT_CUTOFF))))
230 freeMReg (MRs is fs) n
231 = if (n _LT_ ILIT(INT_FLPT_CUTOFF))
232 then MRs (is `unionBS` unitBS IBOX(n)) fs
233 else MRs is (fs `unionBS` unitBS (IBOX(n _SUB_ ILIT(INT_FLPT_CUTOFF))))
236 ------------------------------------------------
237 #if sparc_TARGET_ARCH
238 freeMRegs (MRs is ss ds) xs
239 = MRs (is `unionBS` is2) (ss `unionBS` ss2) (ds `unionBS` ds2)
241 MRs is2 ss2 ds2 = mkMRegsState xs
243 freeMRegs (MRs is fs) xs
244 = MRs (is `unionBS` is2) (fs `unionBS` fs2)
246 MRs is2 fs2 = mkMRegsState xs
250 %************************************************************************
252 \subsection{@RegUsage@ type; @noUsage@, @endUsage@, @regUsage@ functions}
254 %************************************************************************
256 @regUsage@ returns the sets of src and destination registers used by a
257 particular instruction. Machine registers that are pre-allocated to
258 stgRegs are filtered out, because they are uninteresting from a
259 register allocation standpoint. (We wouldn't want them to end up on
262 An important point: The @regUsage@ function for a particular
263 assembly language must not refer to fixed registers, such as Hp, SpA,
264 etc. The source and destination MRegsStates should only refer to
265 dynamically allocated registers or static registers from the free
266 list. As far as we are concerned, the fixed registers simply don't
267 exist (for allocation purposes, anyway).
270 data RegUsage = RU RegSet RegSet
272 noUsage, endUsage :: RegUsage
273 noUsage = RU emptyRegSet emptyRegSet
274 endUsage = RU emptyRegSet freeRegSet
276 regUsage :: Instr -> RegUsage
278 #if alpha_TARGET_ARCH
280 regUsage instr = case instr of
281 LD B reg addr -> usage (regAddr addr, [reg, t9])
282 LD BU reg addr -> usage (regAddr addr, [reg, t9])
283 -- LD W reg addr -> usage (regAddr addr, [reg, t9]) : UNUSED
284 -- LD WU reg addr -> usage (regAddr addr, [reg, t9]) : UNUSED
285 LD sz reg addr -> usage (regAddr addr, [reg])
286 LDA reg addr -> usage (regAddr addr, [reg])
287 LDAH reg addr -> usage (regAddr addr, [reg])
288 LDGP reg addr -> usage (regAddr addr, [reg])
289 LDI sz reg imm -> usage ([], [reg])
290 ST B reg addr -> usage (reg : regAddr addr, [t9, t10])
291 -- ST W reg addr -> usage (reg : regAddr addr, [t9, t10]) : UNUSED
292 ST sz reg addr -> usage (reg : regAddr addr, [])
293 CLR reg -> usage ([], [reg])
294 ABS sz ri reg -> usage (regRI ri, [reg])
295 NEG sz ov ri reg -> usage (regRI ri, [reg])
296 ADD sz ov r1 ar r2 -> usage (r1 : regRI ar, [r2])
297 SADD sz sc r1 ar r2 -> usage (r1 : regRI ar, [r2])
298 SUB sz ov r1 ar r2 -> usage (r1 : regRI ar, [r2])
299 SSUB sz sc r1 ar r2 -> usage (r1 : regRI ar, [r2])
300 MUL sz ov r1 ar r2 -> usage (r1 : regRI ar, [r2])
301 DIV sz un r1 ar r2 -> usage (r1 : regRI ar, [r2, t9, t10, t11, t12])
302 REM sz un r1 ar r2 -> usage (r1 : regRI ar, [r2, t9, t10, t11, t12])
303 NOT ri reg -> usage (regRI ri, [reg])
304 AND r1 ar r2 -> usage (r1 : regRI ar, [r2])
305 ANDNOT r1 ar r2 -> usage (r1 : regRI ar, [r2])
306 OR r1 ar r2 -> usage (r1 : regRI ar, [r2])
307 ORNOT r1 ar r2 -> usage (r1 : regRI ar, [r2])
308 XOR r1 ar r2 -> usage (r1 : regRI ar, [r2])
309 XORNOT r1 ar r2 -> usage (r1 : regRI ar, [r2])
310 SLL r1 ar r2 -> usage (r1 : regRI ar, [r2])
311 SRL r1 ar r2 -> usage (r1 : regRI ar, [r2])
312 SRA r1 ar r2 -> usage (r1 : regRI ar, [r2])
313 ZAP r1 ar r2 -> usage (r1 : regRI ar, [r2])
314 ZAPNOT r1 ar r2 -> usage (r1 : regRI ar, [r2])
315 CMP co r1 ar r2 -> usage (r1 : regRI ar, [r2])
316 FCLR reg -> usage ([], [reg])
317 FABS r1 r2 -> usage ([r1], [r2])
318 FNEG sz r1 r2 -> usage ([r1], [r2])
319 FADD sz r1 r2 r3 -> usage ([r1, r2], [r3])
320 FDIV sz r1 r2 r3 -> usage ([r1, r2], [r3])
321 FMUL sz r1 r2 r3 -> usage ([r1, r2], [r3])
322 FSUB sz r1 r2 r3 -> usage ([r1, r2], [r3])
323 CVTxy sz1 sz2 r1 r2 -> usage ([r1], [r2])
324 FCMP sz co r1 r2 r3 -> usage ([r1, r2], [r3])
325 FMOV r1 r2 -> usage ([r1], [r2])
328 -- We assume that all local jumps will be BI/BF/BR. JMP must be out-of-line.
329 BI cond reg lbl -> usage ([reg], [])
330 BF cond reg lbl -> usage ([reg], [])
331 JMP reg addr hint -> RU (mkRegSet (filter interesting (regAddr addr))) freeRegSet
333 BSR _ n -> RU (argRegSet n) callClobberedRegSet
334 JSR reg addr n -> RU (argRegSet n) callClobberedRegSet
339 usage (src, dst) = RU (mkRegSet (filter interesting src))
340 (mkRegSet (filter interesting dst))
342 interesting (FixedReg _) = False
345 regAddr (AddrReg r1) = [r1]
346 regAddr (AddrRegImm r1 _) = [r1]
347 regAddr (AddrImm _) = []
349 regRI (RIReg r) = [r]
352 #endif {- alpha_TARGET_ARCH -}
353 -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
356 regUsage instr = case instr of
357 MOV sz src dst -> usage2 src dst
358 MOVZxL sz src dst -> usage2 src dst
359 MOVSxL sz src dst -> usage2 src dst
360 LEA sz src dst -> usage2 src dst
361 ADD sz src dst -> usage2s src dst
362 SUB sz src dst -> usage2s src dst
363 IMUL sz src dst -> usage2s src dst
364 IDIV sz src -> usage (eax:edx:opToReg src) [eax,edx]
365 AND sz src dst -> usage2s src dst
366 OR sz src dst -> usage2s src dst
367 XOR sz src dst -> usage2s src dst
368 NOT sz op -> usage1 op
369 NEGI sz op -> usage1 op
370 SHL sz len dst -> usage2s len dst -- len is either an Imm or ecx.
371 SAR sz len dst -> usage2s len dst -- len is either an Imm or ecx.
372 SHR sz len dst -> usage2s len dst -- len is either an Imm or ecx.
373 BT sz imm src -> usage (opToReg src) []
375 PUSH sz op -> usage (opToReg op) []
376 POP sz op -> usage [] (opToReg op)
377 TEST sz src dst -> usage (opToReg src ++ opToReg dst) []
378 CMP sz src dst -> usage (opToReg src ++ opToReg dst) []
379 SETCC cond op -> usage [] (opToReg op)
380 JXX cond lbl -> usage [] []
381 JMP op -> usage (opToReg op) freeRegs
382 CALL imm -> usage [] callClobberedRegs
383 CLTD -> usage [eax] [edx]
386 GMOV src dst -> usage [src] [dst]
387 GLD sz src dst -> usage (addrToRegs src) [dst]
388 GST sz src dst -> usage [src] (addrToRegs dst)
390 GFTOD src dst -> usage [src] [dst]
391 GFTOI src dst -> usage [src] [dst]
393 GDTOF src dst -> usage [src] [dst]
394 GDTOI src dst -> usage [src] [dst]
396 GITOF src dst -> usage [src] [dst]
397 GITOD src dst -> usage [src] [dst]
399 GADD sz s1 s2 dst -> usage [s1,s2] [dst]
400 GSUB sz s1 s2 dst -> usage [s1,s2] [dst]
401 GMUL sz s1 s2 dst -> usage [s1,s2] [dst]
402 GDIV sz s1 s2 dst -> usage [s1,s2] [dst]
404 GCMP sz src1 src2 -> usage [src1,src2] []
405 GABS sz src dst -> usage [src] [dst]
406 GNEG sz src dst -> usage [src] [dst]
407 GSQRT sz src dst -> usage [src] [dst]
408 GSIN sz src dst -> usage [src] [dst]
409 GCOS sz src dst -> usage [src] [dst]
410 GTAN sz src dst -> usage [src] [dst]
417 _ -> pprPanic "regUsage(x86) " empty
420 -- 2 operand form in which the second operand is purely a destination
421 usage2 :: Operand -> Operand -> RegUsage
422 usage2 op (OpReg reg) = usage (opToReg op) [reg]
423 usage2 op (OpAddr ea) = usage (opToReg op ++ addrToRegs ea) []
424 usage2 op (OpImm imm) = usage (opToReg op) []
426 -- 2 operand form in which the second operand is also an input
427 usage2s :: Operand -> Operand -> RegUsage
428 usage2s op (OpReg reg) = usage (opToReg op ++ [reg]) [reg]
429 usage2s op (OpAddr ea) = usage (opToReg op ++ addrToRegs ea) []
430 usage2s op (OpImm imm) = usage (opToReg op) []
432 -- 1 operand form in which the operand is both used and written
433 usage1 :: Operand -> RegUsage
434 usage1 (OpReg reg) = usage [reg] [reg]
435 usage1 (OpAddr ea) = usage (addrToRegs ea) []
437 allFPRegs = [fake0,fake1,fake2,fake3,fake4,fake5]
439 --callClobberedRegs = [ eax, ecx, edx ] -- according to gcc, anyway.
440 callClobberedRegs = [eax,fake0,fake1,fake2,fake3,fake4,fake5]
442 -- General purpose register collecting functions.
444 opToReg (OpReg reg) = [reg]
445 opToReg (OpImm imm) = []
446 opToReg (OpAddr ea) = addrToRegs ea
448 addrToRegs (AddrBaseIndex base index _) = baseToReg base ++ indexToReg index
449 where baseToReg Nothing = []
450 baseToReg (Just r) = [r]
451 indexToReg Nothing = []
452 indexToReg (Just (r,_)) = [r]
453 addrToRegs (ImmAddr _ _) = []
455 usage src dst = RU (mkRegSet (filter interesting src))
456 (mkRegSet (filter interesting dst))
458 interesting (FixedReg _) = False
462 -- Allow the spiller to decide whether or not it can use
463 -- %eax and %edx as spill temporaries.
464 hasFixedEAXorEDX instr = case instr of
469 #endif {- i386_TARGET_ARCH -}
470 -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
471 #if sparc_TARGET_ARCH
473 regUsage instr = case instr of
474 LD sz addr reg -> usage (regAddr addr, [reg])
475 ST sz reg addr -> usage (reg : regAddr addr, [])
476 ADD x cc r1 ar r2 -> usage (r1 : regRI ar, [r2])
477 SUB x cc r1 ar r2 -> usage (r1 : regRI ar, [r2])
478 AND b r1 ar r2 -> usage (r1 : regRI ar, [r2])
479 ANDN b r1 ar r2 -> usage (r1 : regRI ar, [r2])
480 OR b r1 ar r2 -> usage (r1 : regRI ar, [r2])
481 ORN b r1 ar r2 -> usage (r1 : regRI ar, [r2])
482 XOR b r1 ar r2 -> usage (r1 : regRI ar, [r2])
483 XNOR b r1 ar r2 -> usage (r1 : regRI ar, [r2])
484 SLL r1 ar r2 -> usage (r1 : regRI ar, [r2])
485 SRL r1 ar r2 -> usage (r1 : regRI ar, [r2])
486 SRA r1 ar r2 -> usage (r1 : regRI ar, [r2])
487 SETHI imm reg -> usage ([], [reg])
488 FABS s r1 r2 -> usage ([r1], [r2])
489 FADD s r1 r2 r3 -> usage ([r1, r2], [r3])
490 FCMP e s r1 r2 -> usage ([r1, r2], [])
491 FDIV s r1 r2 r3 -> usage ([r1, r2], [r3])
492 FMOV s r1 r2 -> usage ([r1], [r2])
493 FMUL s r1 r2 r3 -> usage ([r1, r2], [r3])
494 FNEG s r1 r2 -> usage ([r1], [r2])
495 FSQRT s r1 r2 -> usage ([r1], [r2])
496 FSUB s r1 r2 r3 -> usage ([r1, r2], [r3])
497 FxTOy s1 s2 r1 r2 -> usage ([r1], [r2])
499 -- We assume that all local jumps will be BI/BF. JMP must be out-of-line.
500 JMP addr -> RU (mkRegSet (filter interesting (regAddr addr))) freeRegSet
502 CALL _ n True -> endUsage
503 CALL _ n False -> RU (argRegSet n) callClobberedRegSet
507 usage (src, dst) = RU (mkRegSet (filter interesting src))
508 (mkRegSet (filter interesting dst))
510 interesting (FixedReg _) = False
513 regAddr (AddrRegReg r1 r2) = [r1, r2]
514 regAddr (AddrRegImm r1 _) = [r1]
516 regRI (RIReg r) = [r]
519 #endif {- sparc_TARGET_ARCH -}
523 %************************************************************************
525 \subsection{Free, reserved, call-clobbered, and argument registers}
527 %************************************************************************
529 @freeRegs@ is the list of registers we can use in register allocation.
530 @freeReg@ (below) says if a particular register is free.
532 With a per-instruction clobber list, we might be able to get some of
533 these back, but it's probably not worth the hassle.
535 @callClobberedRegs@ ... the obvious.
537 @argRegs@: assuming a call with N arguments, what registers will be
538 used to hold arguments? (NB: it doesn't know whether the arguments
539 are integer or floating-point...)
541 findReservedRegs tells us which regs can be used as spill temporaries.
542 The list of instructions for which we are attempting allocation is
543 supplied. This is so that we can (at least for x86) examine it to
544 discover which registers are being used in a fixed way -- for example,
545 %eax and %edx are used by integer division, so they can't be used as
546 spill temporaries. However, most instruction lists don't do integer
547 division, so we don't want to rule them out altogether.
549 findReservedRegs returns not a list of spill temporaries, but a list
550 of list of them. This is so that the allocator can attempt allocating
551 with at first no spill temps, then if that fails, increasing numbers.
552 For x86 it is important that we minimise the number of regs reserved
553 as spill temporaries, since there are so few. For Alpha and Sparc
554 this isn't a concern; we just ignore the supplied code list and return
555 a singleton list which we know will satisfy all spill demands.
558 findReservedRegs :: [Instr] -> [[RegNo]]
559 findReservedRegs instrs
560 #if alpha_TARGET_ARCH
561 = [[NCG_Reserved_I1, NCG_Reserved_I2,
562 NCG_Reserved_F1, NCG_Reserved_F2]]
564 #if sparc_TARGET_ARCH
565 = [[NCG_Reserved_I1, NCG_Reserved_I2,
566 NCG_Reserved_F1, NCG_Reserved_F2,
567 NCG_Reserved_D1, NCG_Reserved_D2]]
570 -- Sigh. This is where it gets complicated.
571 = -- first of all, try without any at all.
572 map (map mappedRegNo) (
574 -- if that doesn't work, try one integer reg (which might fail)
575 -- and two float regs (which will always fix any float insns)
578 -- dire straits (but still correct): see if we can bag %eax and %edx
579 ++ if any hasFixedEAXorEDX instrs
581 else [ [ecx,edx,fake4,fake5],
582 [ecx,edx,eax,fake4,fake5] ]
587 %************************************************************************
589 \subsection{@RegLiveness@ type; @regLiveness@ function}
591 %************************************************************************
593 @regLiveness@ takes future liveness information and modifies it
594 according to the semantics of branches and labels. (An out-of-line
595 branch clobbers the liveness passed back by the following instruction;
596 a forward local branch passes back the liveness from the target label;
597 a conditional branch merges the liveness from the target and the
598 liveness from its successor; a label stashes away the current liveness
599 in the future liveness environment).
602 data RegLiveness = RL RegSet FutureLive
604 regLiveness :: Instr -> RegLiveness -> RegLiveness
606 regLiveness instr info@(RL live future@(FL all env))
609 = case (lookupFM env lbl) of
611 Nothing -> pprTrace "Missing" (pprCLabel_asm lbl <+> text "in future?")
614 case instr of -- the rest is machine-specific...
616 #if alpha_TARGET_ARCH
618 -- We assume that all local jumps will be BI/BF. JMP must be out-of-line.
620 BR (ImmCLbl lbl) -> RL (lookup lbl) future
621 BI _ _ (ImmCLbl lbl) -> RL (lookup lbl `unionRegSets` live) future
622 BF _ _ (ImmCLbl lbl) -> RL (lookup lbl `unionRegSets` live) future
623 JMP _ _ _ -> RL emptyRegSet future
624 BSR _ _ -> RL live future
625 JSR _ _ _ -> RL live future
626 LABEL lbl -> RL live (FL (all `unionRegSets` live) (addToFM env lbl live))
629 #endif {- alpha_TARGET_ARCH -}
630 -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
633 JXX _ lbl -> RL (lookup lbl `unionRegSets` live) future
634 JMP _ -> RL emptyRegSet future
635 CALL _ -> RL live future
636 LABEL lbl -> RL live (FL (all `unionRegSets` live) (addToFM env lbl live))
639 #endif {- i386_TARGET_ARCH -}
640 -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
641 #if sparc_TARGET_ARCH
643 -- We assume that all local jumps will be BI/BF. JMP must be out-of-line.
645 BI ALWAYS _ (ImmCLbl lbl) -> RL (lookup lbl) future
646 BI _ _ (ImmCLbl lbl) -> RL (lookup lbl `unionRegSets` live) future
647 BF ALWAYS _ (ImmCLbl lbl) -> RL (lookup lbl) future
648 BF _ _ (ImmCLbl lbl) -> RL (lookup lbl `unionRegSets` live) future
649 JMP _ -> RL emptyRegSet future
650 CALL _ i True -> RL emptyRegSet future
651 CALL _ i False -> RL live future
652 LABEL lbl -> RL live (FL (all `unionRegSets` live) (addToFM env lbl live))
655 #endif {- sparc_TARGET_ARCH -}
658 %************************************************************************
660 \subsection{@patchRegs@ function}
662 %************************************************************************
664 @patchRegs@ takes an instruction (possibly with
665 MemoryReg/UnmappedReg registers) and changes all register references
666 according to the supplied environment.
669 patchRegs :: Instr -> (Reg -> Reg) -> Instr
671 #if alpha_TARGET_ARCH
673 patchRegs instr env = case instr of
674 LD sz reg addr -> LD sz (env reg) (fixAddr addr)
675 LDA reg addr -> LDA (env reg) (fixAddr addr)
676 LDAH reg addr -> LDAH (env reg) (fixAddr addr)
677 LDGP reg addr -> LDGP (env reg) (fixAddr addr)
678 LDI sz reg imm -> LDI sz (env reg) imm
679 ST sz reg addr -> ST sz (env reg) (fixAddr addr)
680 CLR reg -> CLR (env reg)
681 ABS sz ar reg -> ABS sz (fixRI ar) (env reg)
682 NEG sz ov ar reg -> NEG sz ov (fixRI ar) (env reg)
683 ADD sz ov r1 ar r2 -> ADD sz ov (env r1) (fixRI ar) (env r2)
684 SADD sz sc r1 ar r2 -> SADD sz sc (env r1) (fixRI ar) (env r2)
685 SUB sz ov r1 ar r2 -> SUB sz ov (env r1) (fixRI ar) (env r2)
686 SSUB sz sc r1 ar r2 -> SSUB sz sc (env r1) (fixRI ar) (env r2)
687 MUL sz ov r1 ar r2 -> MUL sz ov (env r1) (fixRI ar) (env r2)
688 DIV sz un r1 ar r2 -> DIV sz un (env r1) (fixRI ar) (env r2)
689 REM sz un r1 ar r2 -> REM sz un (env r1) (fixRI ar) (env r2)
690 NOT ar reg -> NOT (fixRI ar) (env reg)
691 AND r1 ar r2 -> AND (env r1) (fixRI ar) (env r2)
692 ANDNOT r1 ar r2 -> ANDNOT (env r1) (fixRI ar) (env r2)
693 OR r1 ar r2 -> OR (env r1) (fixRI ar) (env r2)
694 ORNOT r1 ar r2 -> ORNOT (env r1) (fixRI ar) (env r2)
695 XOR r1 ar r2 -> XOR (env r1) (fixRI ar) (env r2)
696 XORNOT r1 ar r2 -> XORNOT (env r1) (fixRI ar) (env r2)
697 SLL r1 ar r2 -> SLL (env r1) (fixRI ar) (env r2)
698 SRL r1 ar r2 -> SRL (env r1) (fixRI ar) (env r2)
699 SRA r1 ar r2 -> SRA (env r1) (fixRI ar) (env r2)
700 ZAP r1 ar r2 -> ZAP (env r1) (fixRI ar) (env r2)
701 ZAPNOT r1 ar r2 -> ZAPNOT (env r1) (fixRI ar) (env r2)
702 CMP co r1 ar r2 -> CMP co (env r1) (fixRI ar) (env r2)
703 FCLR reg -> FCLR (env reg)
704 FABS r1 r2 -> FABS (env r1) (env r2)
705 FNEG s r1 r2 -> FNEG s (env r1) (env r2)
706 FADD s r1 r2 r3 -> FADD s (env r1) (env r2) (env r3)
707 FDIV s r1 r2 r3 -> FDIV s (env r1) (env r2) (env r3)
708 FMUL s r1 r2 r3 -> FMUL s (env r1) (env r2) (env r3)
709 FSUB s r1 r2 r3 -> FSUB s (env r1) (env r2) (env r3)
710 CVTxy s1 s2 r1 r2 -> CVTxy s1 s2 (env r1) (env r2)
711 FCMP s co r1 r2 r3 -> FCMP s co (env r1) (env r2) (env r3)
712 FMOV r1 r2 -> FMOV (env r1) (env r2)
713 BI cond reg lbl -> BI cond (env reg) lbl
714 BF cond reg lbl -> BF cond (env reg) lbl
715 JMP reg addr hint -> JMP (env reg) (fixAddr addr) hint
716 JSR reg addr i -> JSR (env reg) (fixAddr addr) i
719 fixAddr (AddrReg r1) = AddrReg (env r1)
720 fixAddr (AddrRegImm r1 i) = AddrRegImm (env r1) i
721 fixAddr other = other
723 fixRI (RIReg r) = RIReg (env r)
726 #endif {- alpha_TARGET_ARCH -}
727 -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
730 patchRegs instr env = case instr of
731 MOV sz src dst -> patch2 (MOV sz) src dst
732 MOVZxL sz src dst -> patch2 (MOVZxL sz) src dst
733 MOVSxL sz src dst -> patch2 (MOVSxL sz) src dst
734 LEA sz src dst -> patch2 (LEA sz) src dst
735 ADD sz src dst -> patch2 (ADD sz) src dst
736 SUB sz src dst -> patch2 (SUB sz) src dst
737 IMUL sz src dst -> patch2 (IMUL sz) src dst
738 IDIV sz src -> patch1 (IDIV sz) src
739 AND sz src dst -> patch2 (AND sz) src dst
740 OR sz src dst -> patch2 (OR sz) src dst
741 XOR sz src dst -> patch2 (XOR sz) src dst
742 NOT sz op -> patch1 (NOT sz) op
743 NEGI sz op -> patch1 (NEGI sz) op
744 SHL sz imm dst -> patch2 (SHL sz) imm dst
745 SAR sz imm dst -> patch2 (SAR sz) imm dst
746 SHR sz imm dst -> patch2 (SHR sz) imm dst
747 BT sz imm src -> patch1 (BT sz imm) src
748 TEST sz src dst -> patch2 (TEST sz) src dst
749 CMP sz src dst -> patch2 (CMP sz) src dst
750 PUSH sz op -> patch1 (PUSH sz) op
751 POP sz op -> patch1 (POP sz) op
752 SETCC cond op -> patch1 (SETCC cond) op
753 JMP op -> patch1 JMP op
755 GMOV src dst -> GMOV (env src) (env dst)
756 GLD sz src dst -> GLD sz (lookupAddr src) (env dst)
757 GST sz src dst -> GST sz (env src) (lookupAddr dst)
759 GFTOD src dst -> GFTOD (env src) (env dst)
760 GFTOI src dst -> GFTOI (env src) (env dst)
762 GDTOF src dst -> GDTOF (env src) (env dst)
763 GDTOI src dst -> GDTOI (env src) (env dst)
765 GITOF src dst -> GITOF (env src) (env dst)
766 GITOD src dst -> GITOD (env src) (env dst)
768 GADD sz s1 s2 dst -> GADD sz (env s1) (env s2) (env dst)
769 GSUB sz s1 s2 dst -> GSUB sz (env s1) (env s2) (env dst)
770 GMUL sz s1 s2 dst -> GMUL sz (env s1) (env s2) (env dst)
771 GDIV sz s1 s2 dst -> GDIV sz (env s1) (env s2) (env dst)
773 GCMP sz src1 src2 -> GCMP sz (env src1) (env src2)
774 GABS sz src dst -> GABS sz (env src) (env dst)
775 GNEG sz src dst -> GNEG sz (env src) (env dst)
776 GSQRT sz src dst -> GSQRT sz (env src) (env dst)
777 GSIN sz src dst -> GSIN sz (env src) (env dst)
778 GCOS sz src dst -> GCOS sz (env src) (env dst)
779 GTAN sz src dst -> GTAN sz (env src) (env dst)
789 _ -> pprPanic "patchInstr(x86)" empty
792 patch1 insn op = insn (patchOp op)
793 patch2 insn src dst = insn (patchOp src) (patchOp dst)
795 patchOp (OpReg reg) = OpReg (env reg)
796 patchOp (OpImm imm) = OpImm imm
797 patchOp (OpAddr ea) = OpAddr (lookupAddr ea)
799 lookupAddr (ImmAddr imm off) = ImmAddr imm off
800 lookupAddr (AddrBaseIndex base index disp)
801 = AddrBaseIndex (lookupBase base) (lookupIndex index) disp
803 lookupBase Nothing = Nothing
804 lookupBase (Just r) = Just (env r)
806 lookupIndex Nothing = Nothing
807 lookupIndex (Just (r,i)) = Just (env r, i)
809 #endif {- i386_TARGET_ARCH -}
810 -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
811 #if sparc_TARGET_ARCH
813 patchRegs instr env = case instr of
814 LD sz addr reg -> LD sz (fixAddr addr) (env reg)
815 ST sz reg addr -> ST sz (env reg) (fixAddr addr)
816 ADD x cc r1 ar r2 -> ADD x cc (env r1) (fixRI ar) (env r2)
817 SUB x cc r1 ar r2 -> SUB x cc (env r1) (fixRI ar) (env r2)
818 AND b r1 ar r2 -> AND b (env r1) (fixRI ar) (env r2)
819 ANDN b r1 ar r2 -> ANDN b (env r1) (fixRI ar) (env r2)
820 OR b r1 ar r2 -> OR b (env r1) (fixRI ar) (env r2)
821 ORN b r1 ar r2 -> ORN b (env r1) (fixRI ar) (env r2)
822 XOR b r1 ar r2 -> XOR b (env r1) (fixRI ar) (env r2)
823 XNOR b r1 ar r2 -> XNOR b (env r1) (fixRI ar) (env r2)
824 SLL r1 ar r2 -> SLL (env r1) (fixRI ar) (env r2)
825 SRL r1 ar r2 -> SRL (env r1) (fixRI ar) (env r2)
826 SRA r1 ar r2 -> SRA (env r1) (fixRI ar) (env r2)
827 SETHI imm reg -> SETHI imm (env reg)
828 FABS s r1 r2 -> FABS s (env r1) (env r2)
829 FADD s r1 r2 r3 -> FADD s (env r1) (env r2) (env r3)
830 FCMP e s r1 r2 -> FCMP e s (env r1) (env r2)
831 FDIV s r1 r2 r3 -> FDIV s (env r1) (env r2) (env r3)
832 FMOV s r1 r2 -> FMOV s (env r1) (env r2)
833 FMUL s r1 r2 r3 -> FMUL s (env r1) (env r2) (env r3)
834 FNEG s r1 r2 -> FNEG s (env r1) (env r2)
835 FSQRT s r1 r2 -> FSQRT s (env r1) (env r2)
836 FSUB s r1 r2 r3 -> FSUB s (env r1) (env r2) (env r3)
837 FxTOy s1 s2 r1 r2 -> FxTOy s1 s2 (env r1) (env r2)
838 JMP addr -> JMP (fixAddr addr)
841 fixAddr (AddrRegReg r1 r2) = AddrRegReg (env r1) (env r2)
842 fixAddr (AddrRegImm r1 i) = AddrRegImm (env r1) i
844 fixRI (RIReg r) = RIReg (env r)
847 #endif {- sparc_TARGET_ARCH -}
850 %************************************************************************
852 \subsection{@spillReg@ and @loadReg@ functions}
854 %************************************************************************
856 Spill to memory, and load it back...
858 JRS, 000122: on x86, don't spill directly above the stack pointer, since
859 some insn sequences (int <-> conversions) use this as a temp location.
860 Leave 16 bytes of slop.
863 spillReg, loadReg :: Reg -> Reg -> InstrList
865 spillReg dyn (MemoryReg i pk)
866 | i >= 0 -- JRS paranoia
867 = let sz = primRepToSize pk
870 {-Alpha: spill below the stack pointer (?)-}
871 IF_ARCH_alpha( ST sz dyn (spRel i)
873 {-I386: spill above stack pointer leaving 2 words/spill-}
874 ,IF_ARCH_i386 ( let loc | i < 60 = 4 + 2 * i
875 | otherwise = -2000 - 2 * i
877 if pk == FloatRep || pk == DoubleRep
878 then GST DF dyn (spRel loc)
879 else MOV sz (OpReg dyn) (OpAddr (spRel loc))
881 {-SPARC: spill below frame pointer leaving 2 words/spill-}
882 ,IF_ARCH_sparc( ST sz dyn (fpRel (-2 * i))
886 = pprPanic "spillReg:" (text "invalid spill location: " <> int i)
888 ----------------------------
889 loadReg (MemoryReg i pk) dyn
890 | i >= 0 -- JRS paranoia
891 = let sz = primRepToSize pk
894 IF_ARCH_alpha( LD sz dyn (spRel i)
895 ,IF_ARCH_i386 ( let loc | i < 60 = 4 + 2 * i
896 | otherwise = -2000 - 2 * i
898 if pk == FloatRep || pk == DoubleRep
899 then GLD DF (spRel loc) dyn
900 else MOV sz (OpAddr (spRel loc)) (OpReg dyn)
901 ,IF_ARCH_sparc( LD sz (fpRel (-2 * i)) dyn
905 = pprPanic "loadReg:" (text "invalid spill location: " <> int i)