module AsmCodeGen ( nativeCodeGen ) where
#include "HsVersions.h"
+#include "nativeGen/NCG.h"
import IO ( Handle )
import List ( intersperse )
import UniqSupply ( returnUs, thenUs, mapUs, initUs,
initUs_, UniqSM, UniqSupply )
import UniqFM ( UniqFM, emptyUFM, addToUFM, lookupUFM )
+import MachMisc ( IF_ARCH_i386(i386_insert_ffrees,) )
+
import Outputable
-import GlaExts (trace) --tmp
-#include "nativeGen/NCG.h"
\end{code}
The 96/03 native-code generator has machine-independent and
codeGen stixFinal
= mapUs genMachCode stixFinal `thenUs` \ dynamic_codes ->
let
- static_instrss = scheduleMachCode dynamic_codes
+ fp_kludge :: [Instr] -> [Instr]
+ fp_kludge = IF_ARCH_i386(i386_insert_ffrees,id)
+
+ static_instrss :: [[Instr]]
+ static_instrss = map fp_kludge (scheduleMachCode dynamic_codes)
docs = map (vcat . map pprInstr) static_instrss
in
returnUs (vcat (intersperse (char ' '
Instr(..), IF_ARCH_i386(Operand(..) COMMA,)
Cond(..),
- Size(..)
-
+ Size(..),
+ IF_ARCH_i386(i386_insert_ffrees COMMA,)
+
#if alpha_TARGET_ARCH
, RI(..)
#endif
import AbsCSyn ( MagicId(..) )
import AbsCUtils ( magicIdPrimRep )
-import CLabel ( CLabel )
+import CLabel ( CLabel, isAsmTemp )
import Const ( mkMachInt, Literal(..) )
import MachRegs ( stgReg, callerSaves, RegLoc(..),
Imm(..), Reg(..),
-}
'$' : s
,{-otherwise-}
- s
+ '.':'L':s
)
---------------------------
-- all the 3-operand fake fp insns are src1 src2 dst
-- and furthermore are constrained to be fp regs only.
+ -- IMPORTANT: keep is_G_insn up to date with any changes here
| GMOV Reg Reg -- src(fpreg), dst(fpreg)
| GLD Size MachRegsAddr Reg -- src, dst(fpreg)
| GST Size Reg MachRegsAddr -- src(fpreg), dst
| GNEG Size Reg Reg -- src, dst
| GSQRT Size Reg Reg -- src, dst
+ | GFREE -- do ffree on all x86 regs; an ugly hack
-- Comparison
| TEST Size Operand Operand
| OpImm Imm -- immediate value
| OpAddr MachRegsAddr -- memory reference
+
+i386_insert_ffrees :: [Instr] -> [Instr]
+i386_insert_ffrees insns
+ | any is_G_instr insns
+ = concatMap ffree_before_nonlocal_transfers insns
+ | otherwise
+ = insns
+
+ffree_before_nonlocal_transfers insn
+ = case insn of
+ CALL _ -> [GFREE, insn]
+ JMP (OpImm (ImmCLbl clbl)) | isAsmTemp clbl -> [insn]
+ JMP _ -> [GFREE, insn]
+ other -> [insn]
+
+
+-- if you ever add a new FP insn to the fake x86 FP insn set,
+-- you must update this too
+is_G_instr :: Instr -> Bool
+is_G_instr instr
+ = case instr of
+ GMOV _ _ -> True; GLD _ _ _ -> True; GST _ _ _ -> True;
+ GFTOD _ _ -> True; GFTOI _ _ -> True;
+ GDTOF _ _ -> True; GDTOI _ _ -> True;
+ GITOF _ _ -> True; GITOD _ _ -> True;
+ GADD _ _ _ _ -> True; GDIV _ _ _ _ -> True
+ GSUB _ _ _ _ -> True; GMUL _ _ _ _ -> True
+ GCMP _ _ _ -> True; GABS _ _ _ -> True
+ GNEG _ _ _ -> True; GSQRT _ _ _ -> True
+ GFREE -> panic "is_G_instr: GFREE (!)"
+ other -> False
+
#endif {- i386_TARGET_ARCH -}
\end{code}
pprInstr (JMP (OpImm imm)) = (<>) (ptext SLIT("\tjmp ")) (pprImm imm)
pprInstr (JMP op) = (<>) (ptext SLIT("\tjmp *")) (pprOperand L op)
-
pprInstr (CALL imm)
- = vcat [ ptext SLIT("\tffree %st(0) ;ffree %st(1) ;ffree %st(2) ;ffree %st(3)"),
- ptext SLIT("\tffree %st(4) ;ffree %st(5) ;ffree %st(6) ;ffree %st(7)"),
- hcat [ ptext SLIT("\tcall "), pprImm imm ]
- ]
+ = (<>) (ptext SLIT("\tcall ")) (pprImm imm)
-- Simulating a flat register set on the x86 FP stack is tricky.
text " ; fdiv ", greg src2 1, text ",%st(0)",
gsemi, gpop dst 1])
+pprInstr GFREE
+ = vcat [ ptext SLIT("\tffree %st(0) ;ffree %st(1) ;ffree %st(2) ;ffree %st(3)"),
+ ptext SLIT("\tffree %st(4) ;ffree %st(5) ;ffree %st(6) ;ffree %st(7)")
+ ]
+
--------------------------
gpush reg offset
= hcat [text "ffree %st(7) ; fld ", greg reg offset]