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
)
---------------------------
| L
| F -- IEEE single-precision floating pt
| DF -- IEEE single-precision floating pt
+ | F80 -- Intel 80-bit internal FP format; only used for spilling
#endif
#if sparc_TARGET_ARCH
= B -- byte (signed)
primRepToSize DataPtrRep = IF_ARCH_alpha( Q, IF_ARCH_i386( L, IF_ARCH_sparc( W ,)))
primRepToSize RetRep = IF_ARCH_alpha( Q, IF_ARCH_i386( L, IF_ARCH_sparc( W ,)))
primRepToSize CostCentreRep = IF_ARCH_alpha( Q, IF_ARCH_i386( L, IF_ARCH_sparc( W ,)))
-primRepToSize CharRep = IF_ARCH_alpha( BU, IF_ARCH_i386( L, IF_ARCH_sparc( BU,)))
+primRepToSize CharRep = IF_ARCH_alpha( BU, IF_ARCH_i386( B, IF_ARCH_sparc( BU,)))
primRepToSize IntRep = IF_ARCH_alpha( Q, IF_ARCH_i386( L, IF_ARCH_sparc( W ,)))
primRepToSize WordRep = IF_ARCH_alpha( Q, IF_ARCH_i386( L, IF_ARCH_sparc( W ,)))
primRepToSize AddrRep = IF_ARCH_alpha( Q, IF_ARCH_i386( L, IF_ARCH_sparc( W ,)))
String -- the literal string
| DATA Size
[Imm]
+ | DELTA Int -- specify current stack offset for
+ -- benefit of subsequent passes
\end{code}
\begin{code}
relevant register. There are only six %fake registers because 2 are
needed for the translation, and x86 has 8 in total.
+The translation is inefficient but is simple and it works. A cleverer
+translation would handle a sequence of insns, simulating the FP stack
+contents, would not impose a fixed mapping from %fake to %st regs, and
+hopefully could avoid most of the redundant reg-reg moves of the
+current translation.
+
+We might as well make use of whatever unique FP facilities Intel have
+chosen to bless us with (let's not be churlish, after all).
+Hence GLDZ and GLD1. Bwahahahahahahaha!
+
\begin{code}
#if i386_TARGET_ARCH
-- Moves.
| MOV Size Operand Operand
- | MOVZX Size Operand Operand -- size is the size of operand 2
- | MOVSX Size Operand Operand -- size is the size of operand 2
+ | MOVZxL Size Operand Operand -- size is the size of operand 1
+ | MOVSxL Size Operand Operand -- size is the size of operand 1
-- Load effective address (also a very useful three-operand add instruction :-)
| XOR Size Operand Operand
| NOT Size Operand
| NEGI Size Operand -- NEG instruction (name clash with Cond)
- | SHL Size Operand Operand -- 1st operand must be an Imm or CL
- | SAR Size Operand Operand -- 1st operand must be an Imm or CL
- | SHR Size Operand Operand -- 1st operand must be an Imm or CL
+ | SHL Size Imm Operand -- Only immediate shifts allowed
+ | SAR Size Imm Operand -- Only immediate shifts allowed
+ | SHR Size Imm Operand -- Only immediate shifts allowed
+ | BT Size Imm Operand
| NOP
--- Float Arithmetic. -- ToDo for 386
+-- Float Arithmetic.
--- Note that we cheat by treating G{ABS,MOV,NEG} of doubles as single instructions
--- right up until we spit them out.
+-- Note that we cheat by treating G{ABS,MOV,NEG} of doubles
+-- as single instructions right up until we spit them out.
-- 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
+ | GLDZ Reg -- dst(fpreg)
+ | GLD1 Reg -- dst(fpreg)
+
| GFTOD Reg Reg -- src(fpreg), dst(fpreg)
| GFTOI Reg Reg -- src(fpreg), dst(intreg)
| GABS Size Reg Reg -- src, dst
| GNEG Size Reg Reg -- src, dst
| GSQRT Size Reg Reg -- src, dst
+ | GSIN Size Reg Reg -- src, dst
+ | GCOS Size Reg Reg -- src, dst
+ | GTAN 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;
+ GLDZ _ -> True; GLD1 _ -> 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
+ GSIN _ _ _ -> True; GCOS _ _ _ -> True; GTAN _ _ _ -> True;
+ GFREE -> panic "is_G_instr: GFREE (!)"
+ other -> False
+
#endif {- i386_TARGET_ARCH -}
\end{code}