b4b6fb5f4be684a9a93f2b360a52e65dca8028a1
[ghc-hetmet.git] / compiler / nativeGen / X86 / Instr.hs
1 -----------------------------------------------------------------------------
2 --
3 -- Machine-dependent assembly language
4 --
5 -- (c) The University of Glasgow 1993-2004
6 --
7 -----------------------------------------------------------------------------
8
9 #include "HsVersions.h"
10 #include "nativeGen/NCG.h"
11
12 module X86.Instr
13 where
14
15 import X86.Cond
16 import X86.Regs
17 import Instruction
18 import Size
19 import RegClass
20 import Reg
21
22 import BlockId
23 import Cmm
24 import FastString
25 import FastBool
26
27 import CLabel
28 import Panic
29
30 -- Size of a PPC memory address, in bytes.
31 --
32 archWordSize :: Size
33 #if i386_TARGET_ARCH
34 archWordSize    = II32
35 #elif x86_64_TARGET_ARCH
36 archWordSize    = II64
37 #else
38 archWordSize    = panic "X86.Instr.archWordSize: not defined"
39 #endif
40
41 -- | Instruction instance for x86 instruction set.
42 instance Instruction Instr where
43         regUsageOfInstr         = x86_regUsageOfInstr
44         patchRegsOfInstr        = x86_patchRegsOfInstr
45         isJumpishInstr          = x86_isJumpishInstr
46         jumpDestsOfInstr        = x86_jumpDestsOfInstr
47         patchJumpInstr          = x86_patchJumpInstr
48         mkSpillInstr            = x86_mkSpillInstr
49         mkLoadInstr             = x86_mkLoadInstr
50         takeDeltaInstr          = x86_takeDeltaInstr
51         isMetaInstr             = x86_isMetaInstr
52         mkRegRegMoveInstr       = x86_mkRegRegMoveInstr
53         takeRegRegMoveInstr     = x86_takeRegRegMoveInstr
54         mkJumpInstr             = x86_mkJumpInstr
55
56
57 -- -----------------------------------------------------------------------------
58 -- Intel x86 instructions
59
60 {-
61 Intel, in their infinite wisdom, selected a stack model for floating
62 point registers on x86.  That might have made sense back in 1979 --
63 nowadays we can see it for the nonsense it really is.  A stack model
64 fits poorly with the existing nativeGen infrastructure, which assumes
65 flat integer and FP register sets.  Prior to this commit, nativeGen
66 could not generate correct x86 FP code -- to do so would have meant
67 somehow working the register-stack paradigm into the register
68 allocator and spiller, which sounds very difficult.
69   
70 We have decided to cheat, and go for a simple fix which requires no
71 infrastructure modifications, at the expense of generating ropey but
72 correct FP code.  All notions of the x86 FP stack and its insns have
73 been removed.  Instead, we pretend (to the instruction selector and
74 register allocator) that x86 has six floating point registers, %fake0
75 .. %fake5, which can be used in the usual flat manner.  We further
76 claim that x86 has floating point instructions very similar to SPARC
77 and Alpha, that is, a simple 3-operand register-register arrangement.
78 Code generation and register allocation proceed on this basis.
79   
80 When we come to print out the final assembly, our convenient fiction
81 is converted to dismal reality.  Each fake instruction is
82 independently converted to a series of real x86 instructions.
83 %fake0 .. %fake5 are mapped to %st(0) .. %st(5).  To do reg-reg
84 arithmetic operations, the two operands are pushed onto the top of the
85 FP stack, the operation done, and the result copied back into the
86 relevant register.  There are only six %fake registers because 2 are
87 needed for the translation, and x86 has 8 in total.
88
89 The translation is inefficient but is simple and it works.  A cleverer
90 translation would handle a sequence of insns, simulating the FP stack
91 contents, would not impose a fixed mapping from %fake to %st regs, and
92 hopefully could avoid most of the redundant reg-reg moves of the
93 current translation.
94
95 We might as well make use of whatever unique FP facilities Intel have
96 chosen to bless us with (let's not be churlish, after all).
97 Hence GLDZ and GLD1.  Bwahahahahahahaha!
98 -}
99
100 {-
101 MORE FLOATING POINT MUSINGS...
102
103 Intel's internal floating point registers are by default 80 bit
104 extended precision.  This means that all operations done on values in
105 registers are done at 80 bits, and unless the intermediate values are
106 truncated to the appropriate size (32 or 64 bits) by storing in
107 memory, calculations in registers will give different results from
108 calculations which pass intermediate values in memory (eg. via
109 function calls).
110
111 One solution is to set the FPU into 64 bit precision mode.  Some OSs
112 do this (eg. FreeBSD) and some don't (eg. Linux).  The problem here is
113 that this will only affect 64-bit precision arithmetic; 32-bit
114 calculations will still be done at 64-bit precision in registers.  So
115 it doesn't solve the whole problem.  
116
117 There's also the issue of what the C library is expecting in terms of
118 precision.  It seems to be the case that glibc on Linux expects the
119 FPU to be set to 80 bit precision, so setting it to 64 bit could have
120 unexpected effects.  Changing the default could have undesirable
121 effects on other 3rd-party library code too, so the right thing would
122 be to save/restore the FPU control word across Haskell code if we were
123 to do this.
124
125 gcc's -ffloat-store gives consistent results by always storing the
126 results of floating-point calculations in memory, which works for both
127 32 and 64-bit precision.  However, it only affects the values of
128 user-declared floating point variables in C, not intermediate results.
129 GHC in -fvia-C mode uses -ffloat-store (see the -fexcess-precision
130 flag).
131
132 Another problem is how to spill floating point registers in the
133 register allocator.  Should we spill the whole 80 bits, or just 64?
134 On an OS which is set to 64 bit precision, spilling 64 is fine.  On
135 Linux, spilling 64 bits will round the results of some operations.
136 This is what gcc does.  Spilling at 80 bits requires taking up a full
137 128 bit slot (so we get alignment).  We spill at 80-bits and ignore
138 the alignment problems.
139
140 In the future, we'll use the SSE registers for floating point.  This
141 requires a CPU that supports SSE2 (ordinary SSE only supports 32 bit
142 precision float ops), which means P4 or Xeon and above.  Using SSE
143 will solve all these problems, because the SSE registers use fixed 32
144 bit or 64 bit precision.
145
146 --SDM 1/2003
147 -}
148
149
150 data Instr
151         -- comment pseudo-op
152         = COMMENT FastString            
153
154         -- some static data spat out during code
155         -- generation.  Will be extracted before
156         -- pretty-printing.
157         | LDATA   Section [CmmStatic]   
158
159         -- start a new basic block.  Useful during
160         -- codegen, removed later.  Preceding 
161         -- instruction should be a jump, as per the
162         -- invariants for a BasicBlock (see Cmm).
163         | NEWBLOCK BlockId              
164
165         -- specify current stack offset for
166         -- benefit of subsequent passes
167         | DELTA   Int
168
169         -- Moves.
170         | MOV         Size Operand Operand
171         | MOVZxL      Size Operand Operand -- size is the size of operand 1
172         | MOVSxL      Size Operand Operand -- size is the size of operand 1
173         -- x86_64 note: plain mov into a 32-bit register always zero-extends
174         -- into the 64-bit reg, in contrast to the 8 and 16-bit movs which
175         -- don't affect the high bits of the register.
176
177         -- Load effective address (also a very useful three-operand add instruction :-)
178         | LEA         Size Operand Operand
179
180         -- Int Arithmetic.
181         | ADD         Size Operand Operand
182         | ADC         Size Operand Operand
183         | SUB         Size Operand Operand
184
185         | MUL         Size Operand Operand
186         | IMUL        Size Operand Operand      -- signed int mul
187         | IMUL2       Size Operand              -- %edx:%eax = operand * %eax
188
189         | DIV         Size Operand              -- eax := eax:edx/op, edx := eax:edx%op
190         | IDIV        Size Operand              -- ditto, but signed
191
192         -- Simple bit-twiddling.
193         | AND         Size Operand Operand
194         | OR          Size Operand Operand
195         | XOR         Size Operand Operand
196         | NOT         Size Operand
197         | NEGI        Size Operand              -- NEG instruction (name clash with Cond)
198
199         -- Shifts (amount may be immediate or %cl only)
200         | SHL         Size Operand{-amount-} Operand
201         | SAR         Size Operand{-amount-} Operand
202         | SHR         Size Operand{-amount-} Operand
203
204         | BT          Size Imm Operand
205         | NOP
206
207         -- x86 Float Arithmetic.
208         -- Note that we cheat by treating G{ABS,MOV,NEG} of doubles 
209         -- as single instructions right up until we spit them out.
210         -- all the 3-operand fake fp insns are src1 src2 dst
211         -- and furthermore are constrained to be fp regs only.
212         -- IMPORTANT: keep is_G_insn up to date with any changes here
213         | GMOV        Reg Reg -- src(fpreg), dst(fpreg)
214         | GLD         Size AddrMode Reg -- src, dst(fpreg)
215         | GST         Size Reg AddrMode -- src(fpreg), dst
216                       
217         | GLDZ        Reg -- dst(fpreg)
218         | GLD1        Reg -- dst(fpreg)
219                       
220         | GFTOI       Reg Reg -- src(fpreg), dst(intreg)
221         | GDTOI       Reg Reg -- src(fpreg), dst(intreg)
222                       
223         | GITOF       Reg Reg -- src(intreg), dst(fpreg)
224         | GITOD       Reg Reg -- src(intreg), dst(fpreg)
225         
226         | GADD        Size Reg Reg Reg -- src1, src2, dst
227         | GDIV        Size Reg Reg Reg -- src1, src2, dst
228         | GSUB        Size Reg Reg Reg -- src1, src2, dst
229         | GMUL        Size Reg Reg Reg -- src1, src2, dst
230         
231                 -- FP compare.  Cond must be `elem` [EQQ, NE, LE, LTT, GE, GTT]
232                 -- Compare src1 with src2; set the Zero flag iff the numbers are
233                 -- comparable and the comparison is True.  Subsequent code must
234                 -- test the %eflags zero flag regardless of the supplied Cond.
235         | GCMP        Cond Reg Reg -- src1, src2
236         
237         | GABS        Size Reg Reg -- src, dst
238         | GNEG        Size Reg Reg -- src, dst
239         | GSQRT       Size Reg Reg -- src, dst
240         | GSIN        Size CLabel CLabel Reg Reg -- src, dst
241         | GCOS        Size CLabel CLabel Reg Reg -- src, dst
242         | GTAN        Size CLabel CLabel Reg Reg -- src, dst
243         
244         | GFREE         -- do ffree on all x86 regs; an ugly hack
245
246
247         -- SSE2 floating point: we use a restricted set of the available SSE2
248         -- instructions for floating-point.
249         -- use MOV for moving (either movss or movsd (movlpd better?))
250         | CVTSS2SD      Reg Reg         -- F32 to F64
251         | CVTSD2SS      Reg Reg         -- F64 to F32
252         | CVTTSS2SIQ    Operand Reg     -- F32 to I32/I64 (with truncation)
253         | CVTTSD2SIQ    Operand Reg     -- F64 to I32/I64 (with truncation)
254         | CVTSI2SS      Operand Reg     -- I32/I64 to F32
255         | CVTSI2SD      Operand Reg     -- I32/I64 to F64
256
257         -- use ADD & SUB for arithmetic.  In both cases, operands
258         -- are  Operand Reg.
259
260         -- SSE2 floating-point division:
261         | FDIV          Size Operand Operand   -- divisor, dividend(dst)
262
263         -- use CMP for comparisons.  ucomiss and ucomisd instructions
264         -- compare single/double prec floating point respectively.
265
266         | SQRT          Size Operand Reg        -- src, dst
267
268
269         -- Comparison
270         | TEST          Size Operand Operand
271         | CMP           Size Operand Operand
272         | SETCC         Cond Operand
273
274         -- Stack Operations.
275         | PUSH          Size Operand
276         | POP           Size Operand
277         -- both unused (SDM):
278         --  | PUSHA
279         --  | POPA
280
281         -- Jumping around.
282         | JMP         Operand
283         | JXX         Cond BlockId  -- includes unconditional branches
284         | JXX_GBL     Cond Imm      -- non-local version of JXX
285         | JMP_TBL     Operand [BlockId]  -- table jump
286         | CALL        (Either Imm Reg) [Reg]
287
288         -- Other things.
289         | CLTD Size              -- sign extend %eax into %edx:%eax
290
291         | FETCHGOT    Reg        -- pseudo-insn for ELF position-independent code
292                                  -- pretty-prints as
293                                  --       call 1f
294                                  -- 1:    popl %reg
295                                  --       addl __GLOBAL_OFFSET_TABLE__+.-1b, %reg
296         | FETCHPC     Reg        -- pseudo-insn for Darwin position-independent code
297                                  -- pretty-prints as
298                                  --       call 1f
299                                  -- 1:    popl %reg
300         
301
302 data Operand
303         = OpReg  Reg            -- register
304         | OpImm  Imm            -- immediate value
305         | OpAddr AddrMode       -- memory reference
306
307
308
309 x86_regUsageOfInstr :: Instr -> RegUsage
310 x86_regUsageOfInstr instr 
311  = case instr of
312     MOV    _ src dst    -> usageRW src dst
313     MOVZxL _ src dst    -> usageRW src dst
314     MOVSxL _ src dst    -> usageRW src dst
315     LEA    _ src dst    -> usageRW src dst
316     ADD    _ src dst    -> usageRM src dst
317     ADC    _ src dst    -> usageRM src dst
318     SUB    _ src dst    -> usageRM src dst
319     IMUL   _ src dst    -> usageRM src dst
320     IMUL2  _ src       -> mkRU (eax:use_R src) [eax,edx]
321     MUL    _ src dst    -> usageRM src dst
322     DIV    _ op -> mkRU (eax:edx:use_R op) [eax,edx]
323     IDIV   _ op -> mkRU (eax:edx:use_R op) [eax,edx]
324     AND    _ src dst    -> usageRM src dst
325     OR     _ src dst    -> usageRM src dst
326
327     XOR    _ (OpReg src) (OpReg dst)
328         | src == dst    -> mkRU [] [dst]
329
330     XOR    _ src dst    -> usageRM src dst
331     NOT    _ op         -> usageM op
332     NEGI   _ op         -> usageM op
333     SHL    _ imm dst    -> usageRM imm dst
334     SAR    _ imm dst    -> usageRM imm dst
335     SHR    _ imm dst    -> usageRM imm dst
336     BT     _ _   src    -> mkRUR (use_R src)
337
338     PUSH   _ op         -> mkRUR (use_R op)
339     POP    _ op         -> mkRU [] (def_W op)
340     TEST   _ src dst    -> mkRUR (use_R src ++ use_R dst)
341     CMP    _ src dst    -> mkRUR (use_R src ++ use_R dst)
342     SETCC  _ op         -> mkRU [] (def_W op)
343     JXX    _ _          -> mkRU [] []
344     JXX_GBL _ _         -> mkRU [] []
345     JMP     op          -> mkRUR (use_R op)
346     JMP_TBL op _        -> mkRUR (use_R op)
347     CALL (Left _)  params   -> mkRU params callClobberedRegs
348     CALL (Right reg) params -> mkRU (reg:params) callClobberedRegs
349     CLTD   _            -> mkRU [eax] [edx]
350     NOP                 -> mkRU [] []
351
352 #if i386_TARGET_ARCH
353     GMOV   src dst      -> mkRU [src] [dst]
354     GLD    _ src dst    -> mkRU (use_EA src) [dst]
355     GST    _ src dst    -> mkRUR (src : use_EA dst)
356
357     GLDZ   dst          -> mkRU [] [dst]
358     GLD1   dst          -> mkRU [] [dst]
359
360     GFTOI  src dst      -> mkRU [src] [dst]
361     GDTOI  src dst      -> mkRU [src] [dst]
362
363     GITOF  src dst      -> mkRU [src] [dst]
364     GITOD  src dst      -> mkRU [src] [dst]
365
366     GADD   _ s1 s2 dst  -> mkRU [s1,s2] [dst]
367     GSUB   _ s1 s2 dst  -> mkRU [s1,s2] [dst]
368     GMUL   _ s1 s2 dst  -> mkRU [s1,s2] [dst]
369     GDIV   _ s1 s2 dst  -> mkRU [s1,s2] [dst]
370
371     GCMP   _ src1 src2   -> mkRUR [src1,src2]
372     GABS   _ src dst     -> mkRU [src] [dst]
373     GNEG   _ src dst     -> mkRU [src] [dst]
374     GSQRT  _ src dst     -> mkRU [src] [dst]
375     GSIN   _ _ _ src dst -> mkRU [src] [dst]
376     GCOS   _ _ _ src dst -> mkRU [src] [dst]
377     GTAN   _ _ _ src dst -> mkRU [src] [dst]
378 #endif
379
380 #if x86_64_TARGET_ARCH
381     CVTSS2SD   src dst  -> mkRU [src] [dst]
382     CVTSD2SS   src dst  -> mkRU [src] [dst]
383     CVTTSS2SIQ src dst  -> mkRU (use_R src) [dst]
384     CVTTSD2SIQ src dst  -> mkRU (use_R src) [dst]
385     CVTSI2SS   src dst  -> mkRU (use_R src) [dst]
386     CVTSI2SD   src dst  -> mkRU (use_R src) [dst]
387     FDIV _     src dst  -> usageRM src dst
388 #endif    
389
390     FETCHGOT reg        -> mkRU [] [reg]
391     FETCHPC  reg        -> mkRU [] [reg]
392
393     COMMENT _           -> noUsage
394     DELTA   _           -> noUsage
395
396     _other              -> panic "regUsage: unrecognised instr"
397
398  where
399     -- 2 operand form; first operand Read; second Written
400     usageRW :: Operand -> Operand -> RegUsage
401     usageRW op (OpReg reg)      = mkRU (use_R op) [reg]
402     usageRW op (OpAddr ea)      = mkRUR (use_R op ++ use_EA ea)
403     usageRW _ _                 = panic "X86.RegInfo.usageRW: no match"
404
405     -- 2 operand form; first operand Read; second Modified
406     usageRM :: Operand -> Operand -> RegUsage
407     usageRM op (OpReg reg)      = mkRU (use_R op ++ [reg]) [reg]
408     usageRM op (OpAddr ea)      = mkRUR (use_R op ++ use_EA ea)
409     usageRM _ _                 = panic "X86.RegInfo.usageRM: no match"
410
411     -- 1 operand form; operand Modified
412     usageM :: Operand -> RegUsage
413     usageM (OpReg reg)          = mkRU [reg] [reg]
414     usageM (OpAddr ea)          = mkRUR (use_EA ea)
415     usageM _                    = panic "X86.RegInfo.usageM: no match"
416
417     -- Registers defd when an operand is written.
418     def_W (OpReg reg)           = [reg]
419     def_W (OpAddr _ )           = []
420     def_W _                     = panic "X86.RegInfo.def_W: no match"
421
422     -- Registers used when an operand is read.
423     use_R (OpReg reg)  = [reg]
424     use_R (OpImm _)    = []
425     use_R (OpAddr ea)  = use_EA ea
426
427     -- Registers used to compute an effective address.
428     use_EA (ImmAddr _ _) = []
429     use_EA (AddrBaseIndex base index _) = 
430         use_base base $! use_index index
431         where use_base (EABaseReg r) x = r : x
432               use_base _ x             = x
433               use_index EAIndexNone   = []
434               use_index (EAIndex i _) = [i]
435
436     mkRUR src = src' `seq` RU src' []
437         where src' = filter interesting src
438
439     mkRU src dst = src' `seq` dst' `seq` RU src' dst'
440         where src' = filter interesting src
441               dst' = filter interesting dst
442
443 interesting :: Reg -> Bool
444 interesting (VirtualRegI  _)  = True
445 interesting (VirtualRegHi _)  = True
446 interesting (VirtualRegF  _)  = True
447 interesting (VirtualRegD  _)  = True
448 interesting (RealReg i)       = isFastTrue (freeReg i)
449
450
451
452
453 x86_patchRegsOfInstr :: Instr -> (Reg -> Reg) -> Instr
454 x86_patchRegsOfInstr instr env 
455  = case instr of
456     MOV  sz src dst     -> patch2 (MOV  sz) src dst
457     MOVZxL sz src dst   -> patch2 (MOVZxL sz) src dst
458     MOVSxL sz src dst   -> patch2 (MOVSxL sz) src dst
459     LEA  sz src dst     -> patch2 (LEA  sz) src dst
460     ADD  sz src dst     -> patch2 (ADD  sz) src dst
461     ADC  sz src dst     -> patch2 (ADC  sz) src dst
462     SUB  sz src dst     -> patch2 (SUB  sz) src dst
463     IMUL sz src dst     -> patch2 (IMUL sz) src dst
464     IMUL2 sz src        -> patch1 (IMUL2 sz) src
465     MUL sz src dst      -> patch2 (MUL sz) src dst
466     IDIV sz op          -> patch1 (IDIV sz) op
467     DIV sz op           -> patch1 (DIV sz) op
468     AND  sz src dst     -> patch2 (AND  sz) src dst
469     OR   sz src dst     -> patch2 (OR   sz) src dst
470     XOR  sz src dst     -> patch2 (XOR  sz) src dst
471     NOT  sz op          -> patch1 (NOT  sz) op
472     NEGI sz op          -> patch1 (NEGI sz) op
473     SHL  sz imm dst     -> patch1 (SHL sz imm) dst
474     SAR  sz imm dst     -> patch1 (SAR sz imm) dst
475     SHR  sz imm dst     -> patch1 (SHR sz imm) dst
476     BT   sz imm src     -> patch1 (BT  sz imm) src
477     TEST sz src dst     -> patch2 (TEST sz) src dst
478     CMP  sz src dst     -> patch2 (CMP  sz) src dst
479     PUSH sz op          -> patch1 (PUSH sz) op
480     POP  sz op          -> patch1 (POP  sz) op
481     SETCC cond op       -> patch1 (SETCC cond) op
482     JMP op              -> patch1 JMP op
483     JMP_TBL op ids      -> patch1 JMP_TBL op $ ids
484
485 #if i386_TARGET_ARCH
486     GMOV src dst        -> GMOV (env src) (env dst)
487     GLD  sz src dst     -> GLD sz (lookupAddr src) (env dst)
488     GST  sz src dst     -> GST sz (env src) (lookupAddr dst)
489
490     GLDZ dst            -> GLDZ (env dst)
491     GLD1 dst            -> GLD1 (env dst)
492
493     GFTOI src dst       -> GFTOI (env src) (env dst)
494     GDTOI src dst       -> GDTOI (env src) (env dst)
495
496     GITOF src dst       -> GITOF (env src) (env dst)
497     GITOD src dst       -> GITOD (env src) (env dst)
498
499     GADD sz s1 s2 dst   -> GADD sz (env s1) (env s2) (env dst)
500     GSUB sz s1 s2 dst   -> GSUB sz (env s1) (env s2) (env dst)
501     GMUL sz s1 s2 dst   -> GMUL sz (env s1) (env s2) (env dst)
502     GDIV sz s1 s2 dst   -> GDIV sz (env s1) (env s2) (env dst)
503
504     GCMP sz src1 src2   -> GCMP sz (env src1) (env src2)
505     GABS sz src dst     -> GABS sz (env src) (env dst)
506     GNEG sz src dst     -> GNEG sz (env src) (env dst)
507     GSQRT sz src dst    -> GSQRT sz (env src) (env dst)
508     GSIN sz l1 l2 src dst       -> GSIN sz l1 l2 (env src) (env dst)
509     GCOS sz l1 l2 src dst       -> GCOS sz l1 l2 (env src) (env dst)
510     GTAN sz l1 l2 src dst       -> GTAN sz l1 l2 (env src) (env dst)
511 #endif
512
513 #if x86_64_TARGET_ARCH
514     CVTSS2SD src dst    -> CVTSS2SD (env src) (env dst)
515     CVTSD2SS src dst    -> CVTSD2SS (env src) (env dst)
516     CVTTSS2SIQ src dst  -> CVTTSS2SIQ (patchOp src) (env dst)
517     CVTTSD2SIQ src dst  -> CVTTSD2SIQ (patchOp src) (env dst)
518     CVTSI2SS src dst    -> CVTSI2SS (patchOp src) (env dst)
519     CVTSI2SD src dst    -> CVTSI2SD (patchOp src) (env dst)
520     FDIV sz src dst     -> FDIV sz (patchOp src) (patchOp dst)
521 #endif    
522
523     CALL (Left _)  _    -> instr
524     CALL (Right reg) p  -> CALL (Right (env reg)) p
525     
526     FETCHGOT reg        -> FETCHGOT (env reg)
527     FETCHPC  reg        -> FETCHPC  (env reg)
528    
529     NOP                 -> instr
530     COMMENT _           -> instr
531     DELTA _             -> instr
532
533     JXX _ _             -> instr
534     JXX_GBL _ _         -> instr
535     CLTD _              -> instr
536
537     _other              -> panic "patchRegs: unrecognised instr"
538
539   where
540     patch1 insn op      = insn $! patchOp op
541     patch2 insn src dst = (insn $! patchOp src) $! patchOp dst
542
543     patchOp (OpReg  reg) = OpReg $! env reg
544     patchOp (OpImm  imm) = OpImm imm
545     patchOp (OpAddr ea)  = OpAddr $! lookupAddr ea
546
547     lookupAddr (ImmAddr imm off) = ImmAddr imm off
548     lookupAddr (AddrBaseIndex base index disp)
549       = ((AddrBaseIndex $! lookupBase base) $! lookupIndex index) disp
550       where
551         lookupBase EABaseNone       = EABaseNone
552         lookupBase EABaseRip        = EABaseRip
553         lookupBase (EABaseReg r)    = EABaseReg (env r)
554                                  
555         lookupIndex EAIndexNone     = EAIndexNone
556         lookupIndex (EAIndex r i)   = EAIndex (env r) i
557
558
559 --------------------------------------------------------------------------------
560 x86_isJumpishInstr 
561         :: Instr -> Bool
562
563 x86_isJumpishInstr instr
564  = case instr of
565         JMP{}           -> True
566         JXX{}           -> True
567         JXX_GBL{}       -> True
568         JMP_TBL{}       -> True
569         CALL{}          -> True
570         _               -> False
571
572
573 x86_jumpDestsOfInstr
574         :: Instr 
575         -> [BlockId]
576
577 x86_jumpDestsOfInstr insn 
578   = case insn of
579         JXX _ id        -> [id]
580         JMP_TBL _ ids   -> ids
581         _               -> []
582
583
584 x86_patchJumpInstr 
585         :: Instr -> (BlockId -> BlockId) -> Instr
586
587 x86_patchJumpInstr insn patchF
588   = case insn of
589         JXX cc id       -> JXX cc (patchF id)
590         JMP_TBL _ _     -> error "Cannot patch JMP_TBL"
591         _               -> insn
592
593
594
595
596 -- -----------------------------------------------------------------------------
597 -- | Make a spill instruction.
598 x86_mkSpillInstr
599         :: Reg          -- register to spill
600         -> Int          -- current stack delta
601         -> Int          -- spill slot to use
602         -> Instr
603
604 #if   i386_TARGET_ARCH
605 x86_mkSpillInstr reg delta slot
606   = let off     = spillSlotToOffset slot
607     in
608     let off_w = (off-delta) `div` 4
609     in case regClass reg of
610            RcInteger -> MOV II32 (OpReg reg) (OpAddr (spRel off_w))
611            _         -> GST FF80 reg (spRel off_w) {- RcFloat/RcDouble -}
612
613 #elif x86_64_TARGET_ARCH
614 x86_mkSpillInstr reg delta slot
615   = let off     = spillSlotToOffset slot
616     in
617     let off_w = (off-delta) `div` 8
618     in case regClass reg of
619            RcInteger -> MOV II64 (OpReg reg) (OpAddr (spRel off_w))
620            RcDouble  -> MOV FF64 (OpReg reg) (OpAddr (spRel off_w))
621            _         -> panic "X86.mkSpillInstr: no match"
622                 -- ToDo: will it work to always spill as a double?
623                 -- does that cause a stall if the data was a float?
624 #else
625 x86_mkSpillInstr _ _ _
626     =   panic "X86.RegInfo.mkSpillInstr: not defined for this architecture."
627 #endif
628
629
630 -- | Make a spill reload instruction.
631 x86_mkLoadInstr
632         :: Reg          -- register to load
633         -> Int          -- current stack delta
634         -> Int          -- spill slot to use
635         -> Instr
636
637 #if   i386_TARGET_ARCH
638 x86_mkLoadInstr reg delta slot
639   = let off     = spillSlotToOffset slot
640     in
641         let off_w = (off-delta) `div` 4
642         in case regClass reg of {
643               RcInteger -> MOV II32 (OpAddr (spRel off_w)) (OpReg reg);
644               _         -> GLD FF80 (spRel off_w) reg} {- RcFloat/RcDouble -}
645 #elif x86_64_TARGET_ARCH
646 x86_mkLoadInstr reg delta slot
647   = let off     = spillSlotToOffset slot
648     in
649         let off_w = (off-delta) `div` 8
650         in case regClass reg of
651               RcInteger -> MOV II64 (OpAddr (spRel off_w)) (OpReg reg)
652               _         -> MOV FF64 (OpAddr (spRel off_w)) (OpReg reg)
653 #else
654 x86_mkLoadInstr _ _ _
655         = panic "X86.RegInfo.mkLoadInstr: not defined for this architecture."
656 #endif
657
658
659 --------------------------------------------------------------------------------
660
661 -- | See if this instruction is telling us the current C stack delta
662 x86_takeDeltaInstr
663         :: Instr
664         -> Maybe Int
665         
666 x86_takeDeltaInstr instr
667  = case instr of
668         DELTA i         -> Just i
669         _               -> Nothing
670
671
672 x86_isMetaInstr
673         :: Instr
674         -> Bool
675         
676 x86_isMetaInstr instr
677  = case instr of
678         COMMENT{}       -> True
679         LDATA{}         -> True
680         NEWBLOCK{}      -> True
681         DELTA{}         -> True
682         _               -> False
683
684
685
686 -- | Make a reg-reg move instruction.
687 --      On SPARC v8 there are no instructions to move directly between
688 --      floating point and integer regs. If we need to do that then we
689 --      have to go via memory.
690 --
691 x86_mkRegRegMoveInstr
692         :: Reg
693         -> Reg
694         -> Instr
695
696 x86_mkRegRegMoveInstr src dst
697  = case regClass src of
698 #if   i386_TARGET_ARCH
699         RcInteger -> MOV II32 (OpReg src) (OpReg dst)
700         RcDouble  -> GMOV src dst
701         RcFloat   -> panic "X86.RegInfo.mkRegRegMoveInstr: no match"
702 #else
703         RcInteger -> MOV II64 (OpReg src) (OpReg dst)
704         RcDouble  -> MOV FF64 (OpReg src) (OpReg dst)
705         RcFloat   -> panic "X86.RegInfo.mkRegRegMoveInstr: no match"
706 #endif
707
708
709 -- | Check whether an instruction represents a reg-reg move.
710 --      The register allocator attempts to eliminate reg->reg moves whenever it can,
711 --      by assigning the src and dest temporaries to the same real register.
712 --
713 x86_takeRegRegMoveInstr
714         :: Instr 
715         -> Maybe (Reg,Reg)
716
717 x86_takeRegRegMoveInstr (MOV _ (OpReg r1) (OpReg r2)) 
718         = Just (r1,r2)
719
720 x86_takeRegRegMoveInstr _  = Nothing
721
722
723 -- | Make an unconditional branch instruction.
724 x86_mkJumpInstr
725         :: BlockId
726         -> [Instr]
727
728 x86_mkJumpInstr id 
729         = [JXX ALWAYS id]
730
731
732
733
734
735 i386_insert_ffrees 
736         :: [GenBasicBlock Instr] 
737         -> [GenBasicBlock Instr]
738
739 i386_insert_ffrees blocks
740    | or (map (any is_G_instr) [ instrs | BasicBlock _ instrs <- blocks ])
741    = map ffree_before_nonlocal_transfers blocks
742
743    | otherwise
744    = blocks
745   where
746    ffree_before_nonlocal_transfers (BasicBlock id insns) 
747      = BasicBlock id (foldr p [] insns)
748      where p insn r = case insn of
749                         CALL _ _ -> GFREE : insn : r
750                         JMP _    -> GFREE : insn : r
751                         _        -> insn : r
752
753 -- if you ever add a new FP insn to the fake x86 FP insn set,
754 -- you must update this too
755 is_G_instr :: Instr -> Bool
756 is_G_instr instr
757    = case instr of
758         GMOV{}          -> True
759         GLD{}           -> True
760         GST{}           -> True
761         GLDZ{}          -> True
762         GLD1{}          -> True
763         GFTOI{}         -> True
764         GDTOI{}         -> True
765         GITOF{}         -> True
766         GITOD{}         -> True
767         GADD{}          -> True
768         GDIV{}          -> True
769         GSUB{}          -> True
770         GMUL{}          -> True
771         GCMP{}          -> True
772         GABS{}          -> True
773         GNEG{}          -> True
774         GSQRT{}         -> True
775         GSIN{}          -> True
776         GCOS{}          -> True
777         GTAN{}          -> True
778         GFREE           -> panic "is_G_instr: GFREE (!)"
779         _               -> False