2 % (c) The AQUA Project, Glasgow University, 1996
4 \section[RegAllocInfo]{Machine-specific info used for register allocation}
6 The (machine-independent) allocator itself is in @AsmRegAlloc@.
9 #include "HsVersions.h"
10 #include "nativeGen/NCG.h"
58 import MachCode ( InstrList(..) )
60 import BitSet ( unitBS, mkBS, minusBS, unionBS, listBS, BitSet )
61 import CLabel ( pprCLabel_asm, CLabel{-instance Ord-} )
62 import FiniteMap ( addToFM, lookupFM )
63 import OrdList ( mkUnitList, OrdList )
64 import PrimRep ( PrimRep(..) )
65 import Stix ( StixTree, CodeSegment )
66 import UniqSet -- quite a bit of it
67 import Unpretty ( uppShow )
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 MOVZX sz src dst -> usage2 src dst
359 MOVSX sz src dst -> usage2 src dst
360 LEA sz src dst -> usage2 src dst
361 ADD sz src dst -> usage2 src dst
362 SUB sz src dst -> usage2 src dst
363 IMUL sz src dst -> usage2 src dst
364 IDIV sz src -> usage (eax:edx:opToReg src) [eax,edx]
365 AND sz src dst -> usage2 src dst
366 OR sz src dst -> usage2 src dst
367 XOR sz src dst -> usage2 src dst
368 NOT sz op -> usage1 op
369 NEGI sz op -> usage1 op
370 SHL sz imm dst -> usage1 dst -- imm has to be an Imm
371 SAR sz imm dst -> usage1 dst -- imm has to be an Imm
372 SHR sz imm dst -> usage1 dst -- imm has to be an Imm
373 PUSH sz op -> usage (opToReg op) []
374 POP sz op -> usage [] (opToReg op)
375 TEST sz src dst -> usage (opToReg src ++ opToReg dst) []
376 CMP sz src dst -> usage (opToReg src ++ opToReg dst) []
377 SETCC cond op -> usage [] (opToReg op)
378 JXX cond label -> usage [] []
379 JMP op -> usage (opToReg op) freeRegs
380 CALL imm -> usage [] callClobberedRegs
381 CLTD -> usage [eax] [edx]
383 SAHF -> usage [eax] []
384 FABS -> usage [st0] [st0]
385 FADD sz src -> usage (st0:opToReg src) [st0] -- allFPRegs
386 FADDP -> usage [st0,st1] [st0] -- allFPRegs
387 FIADD sz asrc -> usage (addrToRegs asrc) [st0]
388 FCHS -> usage [st0] [st0]
389 FCOM sz src -> usage (st0:opToReg src) []
390 FCOS -> usage [st0] [st0]
391 FDIV sz src -> usage (st0:opToReg src) [st0]
392 FDIVP -> usage [st0,st1] [st0]
393 FDIVRP -> usage [st0,st1] [st0]
394 FIDIV sz asrc -> usage (addrToRegs asrc) [st0]
395 FDIVR sz src -> usage (st0:opToReg src) [st0]
396 FIDIVR sz asrc -> usage (addrToRegs asrc) [st0]
397 FICOM sz asrc -> usage (addrToRegs asrc) []
398 FILD sz asrc dst -> usage (addrToRegs asrc) [dst] -- allFPRegs
399 FIST sz adst -> usage (st0:addrToRegs adst) []
400 FLD sz src -> usage (opToReg src) [st0] -- allFPRegs
401 FLD1 -> usage [] [st0] -- allFPRegs
402 FLDZ -> usage [] [st0] -- allFPRegs
403 FMUL sz src -> usage (st0:opToReg src) [st0]
404 FMULP -> usage [st0,st1] [st0]
405 FIMUL sz asrc -> usage (addrToRegs asrc) [st0]
406 FRNDINT -> usage [st0] [st0]
407 FSIN -> usage [st0] [st0]
408 FSQRT -> usage [st0] [st0]
409 FST sz (OpReg r) -> usage [st0] [r]
410 FST sz dst -> usage (st0:opToReg dst) []
411 FSTP sz (OpReg r) -> usage [st0] [r] -- allFPRegs
412 FSTP sz dst -> usage (st0:opToReg dst) [] -- allFPRegs
413 FSUB sz src -> usage (st0:opToReg src) [st0] -- allFPRegs
414 FSUBR sz src -> usage (st0:opToReg src) [st0] -- allFPRegs
415 FISUB sz asrc -> usage (addrToRegs asrc) [st0]
416 FSUBP -> usage [st0,st1] [st0] -- allFPRegs
417 FSUBRP -> usage [st0,st1] [st0] -- allFPRegs
418 FISUBR sz asrc -> usage (addrToRegs asrc) [st0]
419 FTST -> usage [st0] []
420 FCOMP sz op -> usage (st0:opToReg op) [st0] -- allFPRegs
421 FUCOMPP -> usage [st0, st1] [] -- allFPRegs
422 FXCH -> usage [st0, st1] [st0, st1]
423 FNSTSW -> usage [] [eax]
426 usage2 :: Operand -> Operand -> RegUsage
427 usage2 op (OpReg reg) = usage (opToReg op) [reg]
428 usage2 op (OpAddr ea) = usage (opToReg op ++ addrToRegs ea) []
429 usage2 op (OpImm imm) = usage (opToReg op) []
430 usage1 :: Operand -> RegUsage
431 usage1 (OpReg reg) = usage [reg] [reg]
432 usage1 (OpAddr ea) = usage (addrToRegs ea) []
433 allFPRegs = [st0,st1,st2,st3,st4,st5,st6,st7]
435 --callClobberedRegs = [ eax, ecx, edx ] -- according to gcc, anyway.
436 callClobberedRegs = [eax]
438 -- General purpose register collecting functions.
440 opToReg (OpReg reg) = [reg]
441 opToReg (OpImm imm) = []
442 opToReg (OpAddr ea) = addrToRegs ea
444 addrToRegs (Addr base index _) = baseToReg base ++ indexToReg index
445 where baseToReg Nothing = []
446 baseToReg (Just r) = [r]
447 indexToReg Nothing = []
448 indexToReg (Just (r,_)) = [r]
449 addrToRegs (ImmAddr _ _) = []
451 usage src dst = RU (mkRegSet (filter interesting src))
452 (mkRegSet (filter interesting dst))
454 interesting (FixedReg _) = False
457 #endif {- i386_TARGET_ARCH -}
458 -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
459 #if sparc_TARGET_ARCH
461 regUsage instr = case instr of
462 LD sz addr reg -> usage (regAddr addr, [reg])
463 ST sz reg addr -> usage (reg : regAddr addr, [])
464 ADD x cc r1 ar r2 -> usage (r1 : regRI ar, [r2])
465 SUB x cc r1 ar r2 -> usage (r1 : regRI ar, [r2])
466 AND b r1 ar r2 -> usage (r1 : regRI ar, [r2])
467 ANDN b r1 ar r2 -> usage (r1 : regRI ar, [r2])
468 OR b r1 ar r2 -> usage (r1 : regRI ar, [r2])
469 ORN b r1 ar r2 -> usage (r1 : regRI ar, [r2])
470 XOR b r1 ar r2 -> usage (r1 : regRI ar, [r2])
471 XNOR b r1 ar r2 -> usage (r1 : regRI ar, [r2])
472 SLL r1 ar r2 -> usage (r1 : regRI ar, [r2])
473 SRL r1 ar r2 -> usage (r1 : regRI ar, [r2])
474 SRA r1 ar r2 -> usage (r1 : regRI ar, [r2])
475 SETHI imm reg -> usage ([], [reg])
476 FABS s r1 r2 -> usage ([r1], [r2])
477 FADD s r1 r2 r3 -> usage ([r1, r2], [r3])
478 FCMP e s r1 r2 -> usage ([r1, r2], [])
479 FDIV s r1 r2 r3 -> usage ([r1, r2], [r3])
480 FMOV s r1 r2 -> usage ([r1], [r2])
481 FMUL s r1 r2 r3 -> usage ([r1, r2], [r3])
482 FNEG s r1 r2 -> usage ([r1], [r2])
483 FSQRT s r1 r2 -> usage ([r1], [r2])
484 FSUB s r1 r2 r3 -> usage ([r1, r2], [r3])
485 FxTOy s1 s2 r1 r2 -> usage ([r1], [r2])
487 -- We assume that all local jumps will be BI/BF. JMP must be out-of-line.
488 JMP addr -> RU (mkRegSet (filter interesting (regAddr addr))) freeRegSet
490 CALL _ n True -> endUsage
491 CALL _ n False -> RU (argRegSet n) callClobberedRegSet
495 usage (src, dst) = RU (mkRegSet (filter interesting src))
496 (mkRegSet (filter interesting dst))
498 interesting (FixedReg _) = False
501 regAddr (AddrRegReg r1 r2) = [r1, r2]
502 regAddr (AddrRegImm r1 _) = [r1]
504 regRI (RIReg r) = [r]
507 #endif {- sparc_TARGET_ARCH -}
510 %************************************************************************
512 \subsection{@RegLiveness@ type; @regLiveness@ function}
514 %************************************************************************
516 @regLiveness@ takes future liveness information and modifies it
517 according to the semantics of branches and labels. (An out-of-line
518 branch clobbers the liveness passed back by the following instruction;
519 a forward local branch passes back the liveness from the target label;
520 a conditional branch merges the liveness from the target and the
521 liveness from its successor; a label stashes away the current liveness
522 in the future liveness environment).
525 data RegLiveness = RL RegSet FutureLive
527 regLiveness :: Instr -> RegLiveness -> RegLiveness
529 regLiveness instr info@(RL live future@(FL all env))
532 = case (lookupFM env lbl) of
534 Nothing -> trace ("Missing " ++ (uppShow 80 (pprCLabel_asm lbl)) ++
535 " in future?") emptyRegSet
537 case instr of -- the rest is machine-specific...
539 #if alpha_TARGET_ARCH
541 -- We assume that all local jumps will be BI/BF. JMP must be out-of-line.
543 BR (ImmCLbl lbl) -> RL (lookup lbl) future
544 BI _ _ (ImmCLbl lbl) -> RL (lookup lbl `unionRegSets` live) future
545 BF _ _ (ImmCLbl lbl) -> RL (lookup lbl `unionRegSets` live) future
546 JMP _ _ _ -> RL emptyRegSet future
547 BSR _ _ -> RL live future
548 JSR _ _ _ -> RL live future
549 LABEL lbl -> RL live (FL (all `unionRegSets` live) (addToFM env lbl live))
552 #endif {- alpha_TARGET_ARCH -}
553 -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
556 JXX _ lbl -> RL (lookup lbl `unionRegSets` live) future
557 JMP _ -> RL emptyRegSet future
558 CALL _ -> RL live future
559 LABEL lbl -> RL live (FL (all `unionRegSets` live) (addToFM env lbl live))
562 #endif {- i386_TARGET_ARCH -}
563 -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
564 #if sparc_TARGET_ARCH
566 -- We assume that all local jumps will be BI/BF. JMP must be out-of-line.
568 BI ALWAYS _ (ImmCLbl lbl) -> RL (lookup lbl) future
569 BI _ _ (ImmCLbl lbl) -> RL (lookup lbl `unionRegSets` live) future
570 BF ALWAYS _ (ImmCLbl lbl) -> RL (lookup lbl) future
571 BF _ _ (ImmCLbl lbl) -> RL (lookup lbl `unionRegSets` live) future
572 JMP _ -> RL emptyRegSet future
573 CALL _ i True -> RL emptyRegSet future
574 CALL _ i False -> RL live future
575 LABEL lbl -> RL live (FL (all `unionRegSets` live) (addToFM env lbl live))
578 #endif {- sparc_TARGET_ARCH -}
581 %************************************************************************
583 \subsection{@patchRegs@ function}
585 %************************************************************************
587 @patchRegs@ takes an instruction (possibly with
588 MemoryReg/UnmappedReg registers) and changes all register references
589 according to the supplied environment.
592 patchRegs :: Instr -> (Reg -> Reg) -> Instr
594 #if alpha_TARGET_ARCH
596 patchRegs instr env = case instr of
597 LD sz reg addr -> LD sz (env reg) (fixAddr addr)
598 LDA reg addr -> LDA (env reg) (fixAddr addr)
599 LDAH reg addr -> LDAH (env reg) (fixAddr addr)
600 LDGP reg addr -> LDGP (env reg) (fixAddr addr)
601 LDI sz reg imm -> LDI sz (env reg) imm
602 ST sz reg addr -> ST sz (env reg) (fixAddr addr)
603 CLR reg -> CLR (env reg)
604 ABS sz ar reg -> ABS sz (fixRI ar) (env reg)
605 NEG sz ov ar reg -> NEG sz ov (fixRI ar) (env reg)
606 ADD sz ov r1 ar r2 -> ADD sz ov (env r1) (fixRI ar) (env r2)
607 SADD sz sc r1 ar r2 -> SADD sz sc (env r1) (fixRI ar) (env r2)
608 SUB sz ov r1 ar r2 -> SUB sz ov (env r1) (fixRI ar) (env r2)
609 SSUB sz sc r1 ar r2 -> SSUB sz sc (env r1) (fixRI ar) (env r2)
610 MUL sz ov r1 ar r2 -> MUL sz ov (env r1) (fixRI ar) (env r2)
611 DIV sz un r1 ar r2 -> DIV sz un (env r1) (fixRI ar) (env r2)
612 REM sz un r1 ar r2 -> REM sz un (env r1) (fixRI ar) (env r2)
613 NOT ar reg -> NOT (fixRI ar) (env reg)
614 AND r1 ar r2 -> AND (env r1) (fixRI ar) (env r2)
615 ANDNOT r1 ar r2 -> ANDNOT (env r1) (fixRI ar) (env r2)
616 OR r1 ar r2 -> OR (env r1) (fixRI ar) (env r2)
617 ORNOT r1 ar r2 -> ORNOT (env r1) (fixRI ar) (env r2)
618 XOR r1 ar r2 -> XOR (env r1) (fixRI ar) (env r2)
619 XORNOT r1 ar r2 -> XORNOT (env r1) (fixRI ar) (env r2)
620 SLL r1 ar r2 -> SLL (env r1) (fixRI ar) (env r2)
621 SRL r1 ar r2 -> SRL (env r1) (fixRI ar) (env r2)
622 SRA r1 ar r2 -> SRA (env r1) (fixRI ar) (env r2)
623 ZAP r1 ar r2 -> ZAP (env r1) (fixRI ar) (env r2)
624 ZAPNOT r1 ar r2 -> ZAPNOT (env r1) (fixRI ar) (env r2)
625 CMP co r1 ar r2 -> CMP co (env r1) (fixRI ar) (env r2)
626 FCLR reg -> FCLR (env reg)
627 FABS r1 r2 -> FABS (env r1) (env r2)
628 FNEG s r1 r2 -> FNEG s (env r1) (env r2)
629 FADD s r1 r2 r3 -> FADD s (env r1) (env r2) (env r3)
630 FDIV s r1 r2 r3 -> FDIV s (env r1) (env r2) (env r3)
631 FMUL s r1 r2 r3 -> FMUL s (env r1) (env r2) (env r3)
632 FSUB s r1 r2 r3 -> FSUB s (env r1) (env r2) (env r3)
633 CVTxy s1 s2 r1 r2 -> CVTxy s1 s2 (env r1) (env r2)
634 FCMP s co r1 r2 r3 -> FCMP s co (env r1) (env r2) (env r3)
635 FMOV r1 r2 -> FMOV (env r1) (env r2)
636 BI cond reg lbl -> BI cond (env reg) lbl
637 BF cond reg lbl -> BF cond (env reg) lbl
638 JMP reg addr hint -> JMP (env reg) (fixAddr addr) hint
639 JSR reg addr i -> JSR (env reg) (fixAddr addr) i
642 fixAddr (AddrReg r1) = AddrReg (env r1)
643 fixAddr (AddrRegImm r1 i) = AddrRegImm (env r1) i
644 fixAddr other = other
646 fixRI (RIReg r) = RIReg (env r)
649 #endif {- alpha_TARGET_ARCH -}
650 -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
653 patchRegs instr env = case instr of
654 MOV sz src dst -> patch2 (MOV sz) src dst
655 MOVZX sz src dst -> patch2 (MOVZX sz) src dst
656 MOVSX sz src dst -> patch2 (MOVSX sz) src dst
657 LEA sz src dst -> patch2 (LEA sz) src dst
658 ADD sz src dst -> patch2 (ADD sz) src dst
659 SUB sz src dst -> patch2 (SUB sz) src dst
660 IMUL sz src dst -> patch2 (IMUL sz) src dst
661 IDIV sz src -> patch1 (IDIV sz) src
662 AND sz src dst -> patch2 (AND sz) src dst
663 OR sz src dst -> patch2 (OR sz) src dst
664 XOR sz src dst -> patch2 (XOR sz) src dst
665 NOT sz op -> patch1 (NOT sz) op
666 NEGI sz op -> patch1 (NEGI sz) op
667 SHL sz imm dst -> patch1 (SHL sz imm) dst
668 SAR sz imm dst -> patch1 (SAR sz imm) dst
669 SHR sz imm dst -> patch1 (SHR sz imm) dst
670 TEST sz src dst -> patch2 (TEST sz) src dst
671 CMP sz src dst -> patch2 (CMP sz) src dst
672 PUSH sz op -> patch1 (PUSH sz) op
673 POP sz op -> patch1 (POP sz) op
674 SETCC cond op -> patch1 (SETCC cond) op
675 JMP op -> patch1 JMP op
676 FADD sz src -> FADD sz (patchOp src)
677 FIADD sz asrc -> FIADD sz (lookupAddr asrc)
678 FCOM sz src -> patch1 (FCOM sz) src
679 FDIV sz src -> FDIV sz (patchOp src)
680 --FDIVP sz src -> FDIVP sz (patchOp src)
681 FIDIV sz asrc -> FIDIV sz (lookupAddr asrc)
682 FDIVR sz src -> FDIVR sz (patchOp src)
683 --FDIVRP sz src -> FDIVRP sz (patchOp src)
684 FIDIVR sz asrc -> FIDIVR sz (lookupAddr asrc)
685 FICOM sz asrc -> FICOM sz (lookupAddr asrc)
686 FILD sz asrc dst -> FILD sz (lookupAddr asrc) (env dst)
687 FIST sz adst -> FIST sz (lookupAddr adst)
688 FLD sz src -> patch1 (FLD sz) (patchOp src)
689 FMUL sz src -> FMUL sz (patchOp src)
690 --FMULP sz src -> FMULP sz (patchOp src)
691 FIMUL sz asrc -> FIMUL sz (lookupAddr asrc)
692 FST sz dst -> FST sz (patchOp dst)
693 FSTP sz dst -> FSTP sz (patchOp dst)
694 FSUB sz src -> FSUB sz (patchOp src)
695 --FSUBP sz src -> FSUBP sz (patchOp src)
696 FISUB sz asrc -> FISUB sz (lookupAddr asrc)
697 FSUBR sz src -> FSUBR sz (patchOp src)
698 --FSUBRP sz src -> FSUBRP sz (patchOp src)
699 FISUBR sz asrc -> FISUBR sz (lookupAddr asrc)
700 FCOMP sz src -> FCOMP sz (patchOp src)
703 patch1 insn op = insn (patchOp op)
704 patch2 insn src dst = insn (patchOp src) (patchOp dst)
706 patchOp (OpReg reg) = OpReg (env reg)
707 patchOp (OpImm imm) = OpImm imm
708 patchOp (OpAddr ea) = OpAddr (lookupAddr ea)
710 lookupAddr (ImmAddr imm off) = ImmAddr imm off
711 lookupAddr (Addr base index disp)
712 = Addr (lookupBase base) (lookupIndex index) disp
714 lookupBase Nothing = Nothing
715 lookupBase (Just r) = Just (env r)
717 lookupIndex Nothing = Nothing
718 lookupIndex (Just (r,i)) = Just (env r, i)
720 #endif {- i386_TARGET_ARCH -}
721 -- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
722 #if sparc_TARGET_ARCH
724 patchRegs instr env = case instr of
725 LD sz addr reg -> LD sz (fixAddr addr) (env reg)
726 ST sz reg addr -> ST sz (env reg) (fixAddr addr)
727 ADD x cc r1 ar r2 -> ADD x cc (env r1) (fixRI ar) (env r2)
728 SUB x cc r1 ar r2 -> SUB x cc (env r1) (fixRI ar) (env r2)
729 AND b r1 ar r2 -> AND b (env r1) (fixRI ar) (env r2)
730 ANDN b r1 ar r2 -> ANDN b (env r1) (fixRI ar) (env r2)
731 OR b r1 ar r2 -> OR b (env r1) (fixRI ar) (env r2)
732 ORN b r1 ar r2 -> ORN b (env r1) (fixRI ar) (env r2)
733 XOR b r1 ar r2 -> XOR b (env r1) (fixRI ar) (env r2)
734 XNOR b r1 ar r2 -> XNOR b (env r1) (fixRI ar) (env r2)
735 SLL r1 ar r2 -> SLL (env r1) (fixRI ar) (env r2)
736 SRL r1 ar r2 -> SRL (env r1) (fixRI ar) (env r2)
737 SRA r1 ar r2 -> SRA (env r1) (fixRI ar) (env r2)
738 SETHI imm reg -> SETHI imm (env reg)
739 FABS s r1 r2 -> FABS s (env r1) (env r2)
740 FADD s r1 r2 r3 -> FADD s (env r1) (env r2) (env r3)
741 FCMP e s r1 r2 -> FCMP e s (env r1) (env r2)
742 FDIV s r1 r2 r3 -> FDIV s (env r1) (env r2) (env r3)
743 FMOV s r1 r2 -> FMOV s (env r1) (env r2)
744 FMUL s r1 r2 r3 -> FMUL s (env r1) (env r2) (env r3)
745 FNEG s r1 r2 -> FNEG s (env r1) (env r2)
746 FSQRT s r1 r2 -> FSQRT s (env r1) (env r2)
747 FSUB s r1 r2 r3 -> FSUB s (env r1) (env r2) (env r3)
748 FxTOy s1 s2 r1 r2 -> FxTOy s1 s2 (env r1) (env r2)
749 JMP addr -> JMP (fixAddr addr)
752 fixAddr (AddrRegReg r1 r2) = AddrRegReg (env r1) (env r2)
753 fixAddr (AddrRegImm r1 i) = AddrRegImm (env r1) i
755 fixRI (RIReg r) = RIReg (env r)
758 #endif {- sparc_TARGET_ARCH -}
761 %************************************************************************
763 \subsection{@spillReg@ and @loadReg@ functions}
765 %************************************************************************
767 Spill to memory, and load it back...
770 spillReg, loadReg :: Reg -> Reg -> InstrList
772 spillReg dyn (MemoryReg i pk)
774 sz = primRepToSize pk
777 {-Alpha: spill below the stack pointer (?)-}
778 IF_ARCH_alpha( ST sz dyn (spRel i)
780 {-I386: spill below stack pointer leaving 2 words/spill-}
781 ,IF_ARCH_i386 ( MOV sz (OpReg dyn) (OpAddr (spRel (-2 * i)))
783 {-SPARC: spill below frame pointer leaving 2 words/spill-}
784 ,IF_ARCH_sparc( ST sz dyn (fpRel (-2 * i))
788 ----------------------------
789 loadReg (MemoryReg i pk) dyn
791 sz = primRepToSize pk
794 IF_ARCH_alpha( LD sz dyn (spRel i)
795 ,IF_ARCH_i386 ( MOV sz (OpAddr (spRel (-2 * i))) (OpReg dyn)
796 ,IF_ARCH_sparc( LD sz (fpRel (-2 * i)) dyn