-- * Machine instructions
Instr(..),
- Cond(..),
-#if !powerpc_TARGET_ARCH && !i386_TARGET_ARCH
+ Cond(..), condUnsigned, condToSigned, condToUnsigned,
+
+#if !powerpc_TARGET_ARCH && !i386_TARGET_ARCH && !x86_64_TARGET_ARCH
Size(..), machRepSize,
#endif
RI(..),
-#if i386_TARGET_ARCH
+#if i386_TARGET_ARCH || x86_64_TARGET_ARCH
Operand(..),
+#endif
+#if i386_TARGET_ARCH
i386_insert_ffrees,
#endif
#if sparc_TARGET_ARCH
riZero, fpRelEA, moveSp, fPair,
#endif
-#if powerpc_TARGET_ARCH
- condUnsigned, condToSigned,
-#endif
- DestInfo(..), hasDestInfo, pprDests,
-
) where
#include "HsVersions.h"
-#include "../includes/ghcconfig.h"
import MachRegs
import Cmm
import CLabel ( CLabel, pprCLabel )
import Panic ( panic )
import Outputable
-import Config ( cLeadingUnderscore )
import FastString
+import Constants ( wORD_SIZE )
import GLAEXTS
| ULE -- For CMP only
| ULT -- For CMP only
#endif
-#if i386_TARGET_ARCH
+#if i386_TARGET_ARCH || x86_64_TARGET_ARCH
= ALWAYS -- What's really used? ToDo
| EQQ
| GE
| POS
| CARRY
| OFLO
+ | PARITY
+ | NOTPARITY
#endif
#if sparc_TARGET_ARCH
= ALWAYS -- What's really used? ToDo
#endif
deriving Eq -- to make an assertion work
+condUnsigned GU = True
+condUnsigned LU = True
+condUnsigned GEU = True
+condUnsigned LEU = True
+condUnsigned _ = False
+
+condToSigned GU = GTT
+condToSigned LU = LTT
+condToSigned GEU = GE
+condToSigned LEU = LE
+condToSigned x = x
+
+condToUnsigned GTT = GU
+condToUnsigned LTT = LU
+condToUnsigned GE = GEU
+condToUnsigned LE = LEU
+condToUnsigned x = x
-- -----------------------------------------------------------------------------
-- Sizes on this architecture
-- ToDo: it's not clear to me that we need separate signed-vs-unsigned sizes
-- here. I've removed them from the x86 version, we'll see what happens --SDM
-#if !powerpc_TARGET_ARCH && !i386_TARGET_ARCH
+#if !powerpc_TARGET_ARCH && !i386_TARGET_ARCH && !x86_64_TARGET_ARCH
data Size
#if alpha_TARGET_ARCH
= B -- byte
--SDM 1/2003
-}
-#if i386_TARGET_ARCH
+#if i386_TARGET_ARCH || x86_64_TARGET_ARCH
-- data Instr continues...
| MOV MachRep Operand Operand
| MOVZxL MachRep Operand Operand -- size is the size of operand 1
| MOVSxL MachRep Operand Operand -- size is the size of operand 1
+ -- x86_64 note: plain mov into a 32-bit register always zero-extends
+ -- into the 64-bit reg, in contrast to the 8 and 16-bit movs which
+ -- don't affect the high bits of the register.
-- Load effective address (also a very useful three-operand add instruction :-)
| LEA MachRep Operand Operand
| ADD MachRep Operand Operand
| ADC MachRep Operand Operand
| SUB MachRep Operand Operand
- | IMUL MachRep Operand Operand -- signed int mul
- | MUL MachRep Operand Operand -- unsigned int mul
- | IMUL64 Reg Reg
- -- operand1:operand2 := (operand1[31:0] *signed operand2[31:0])
+ | MUL MachRep Operand Operand
+ | IMUL MachRep Operand Operand -- signed int mul
+ | IMUL2 MachRep Operand -- %edx:%eax = operand * %eax
| DIV MachRep Operand -- eax := eax:edx/op, edx := eax:edx%op
| IDIV MachRep Operand -- ditto, but signed
| BT MachRep Imm Operand
| NOP
+#if i386_TARGET_ARCH
-- Float Arithmetic.
-- Note that we cheat by treating G{ABS,MOV,NEG} of doubles
| GTAN MachRep Reg Reg -- src, dst
| GFREE -- do ffree on all x86 regs; an ugly hack
+#endif
+
+#if x86_64_TARGET_ARCH
+-- SSE2 floating point: we use a restricted set of the available SSE2
+-- instructions for floating-point.
+
+ -- use MOV for moving (either movss or movsd (movlpd better?))
+
+ | CVTSS2SD Reg Reg -- F32 to F64
+ | CVTSD2SS Reg Reg -- F64 to F32
+ | CVTSS2SI Operand Reg -- F32 to I32/I64 (with rounding)
+ | CVTSD2SI Operand Reg -- F64 to I32/I64 (with rounding)
+ | CVTSI2SS Operand Reg -- I32/I64 to F32
+ | CVTSI2SD Operand Reg -- I32/I64 to F64
+
+ -- use ADD & SUB for arithmetic. In both cases, operands
+ -- are Operand Reg.
+
+ -- SSE2 floating-point division:
+ | FDIV MachRep Operand Operand -- divisor, dividend(dst)
+
+ -- use CMP for comparisons. ucomiss and ucomisd instructions
+ -- compare single/double prec floating point respectively.
+
+ | SQRT MachRep Operand Reg -- src, dst
+#endif
-- Comparison
| TEST MachRep Operand Operand
| PUSH MachRep Operand
| POP MachRep Operand
-- both unused (SDM):
- -- | PUSHA
- -- | POPA
+ -- | PUSHA
+ -- | POPA
-- Jumping around.
| JMP Operand
| JXX Cond BlockId -- includes unconditional branches
| JMP_TBL Operand [BlockId] -- table jump
- | CALL (Either Imm Reg)
+ | CALL (Either Imm Reg) [Reg]
-- Other things.
- | CLTD -- sign extend %eax into %edx:%eax
+ | CLTD MachRep -- sign extend %eax into %edx:%eax
- | FETCHGOT Reg -- pseudo-insn for position-independent code
+ | FETCHGOT Reg -- pseudo-insn for ELF position-independent code
-- pretty-prints as
-- call 1f
-- 1: popl %reg
-- addl __GLOBAL_OFFSET_TABLE__+.-1b, %reg
-
+ | FETCHPC Reg -- pseudo-insn for Darwin position-independent code
+ -- pretty-prints as
+ -- call 1f
+ -- 1: popl %reg
+
+
data Operand
= OpReg Reg -- register
| OpImm Imm -- immediate value
| OpAddr AddrMode -- memory reference
+#endif /* i386 or x86_64 */
+#if i386_TARGET_ARCH
i386_insert_ffrees :: [Instr] -> [Instr]
i386_insert_ffrees insns
| any is_G_instr insns
ffree_before_nonlocal_transfers insn
= case insn of
- CALL _ -> [GFREE, insn]
- JMP _ -> [GFREE, insn]
- other -> [insn]
+ CALL _ _ -> [GFREE, insn]
+ JMP _ -> [GFREE, insn]
+ other -> [insn]
-- if you ever add a new FP insn to the fake x86 FP insn set,
is_G_instr :: Instr -> Bool
is_G_instr instr
= case instr of
- GMOV _ _ -> True; GLD _ _ _ -> True; GST _ _ _ -> True;
- GLDZ _ -> True; GLD1 _ -> True;
- GFTOI _ _ -> True; GDTOI _ _ -> True;
- GITOF _ _ -> True; GITOD _ _ -> True;
+ GMOV _ _ -> True; GLD _ _ _ -> True; GST _ _ _ -> True
+ GLDZ _ -> True; GLD1 _ -> True
+ GFTOI _ _ -> 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;
+ GSIN _ _ _ -> True; GCOS _ _ _ -> True; GTAN _ _ _ -> True
GFREE -> panic "is_G_instr: GFREE (!)"
other -> False
-
#endif /* i386_TARGET_ARCH */
| BI Cond Bool Imm -- cond, annul?, target
| BF Cond Bool Imm -- cond, annul?, target
- | JMP DestInfo AddrMode -- target
+ | JMP AddrMode -- target
| CALL (Either Imm Reg) Int Bool -- target, args, terminal
-data RI = RIReg Reg
- | RIImm Imm
-
riZero :: RI -> Bool
riZero (RIImm (ImmInt 0)) = True
-- alas -- can't have fpRelEA here because of module dependencies.
fpRelEA :: Int -> Reg -> Instr
fpRelEA n dst
- = ADD False False fp (RIImm (ImmInt (n * BYTES_PER_WORD))) dst
+ = ADD False False fp (RIImm (ImmInt (n * wORD_SIZE))) dst
-- Code to shift the stack pointer by n words.
moveSp :: Int -> Instr
moveSp n
- = ADD False False sp (RIImm (ImmInt (n * BYTES_PER_WORD))) sp
+ = ADD False False sp (RIImm (ImmInt (n * wORD_SIZE))) sp
-- Produce the second-half-of-a-double register given the first half.
fPair :: Reg -> Reg
| FETCHPC Reg -- pseudo-instruction:
-- bcl to next insn, mflr reg
-condUnsigned GU = True
-condUnsigned LU = True
-condUnsigned GEU = True
-condUnsigned LEU = True
-condUnsigned _ = False
-
-condToSigned GU = GTT
-condToSigned LU = LTT
-condToSigned GEU = GE
-condToSigned LEU = LE
-condToSigned x = x
#endif /* powerpc_TARGET_ARCH */
-
-
--- -----------------------------------------------------------------------------
--- DestInfo
-
--- ToDo: might not be needed anymore --SDM
-
--- used by insnFuture in RegAllocInfo.lhs
-data DestInfo
- = NoDestInfo -- no supplied dests; infer from context
- | DestInfo [CLabel] -- precisely these dests and no others
-
-hasDestInfo NoDestInfo = False
-hasDestInfo (DestInfo _) = True
-
-pprDests :: DestInfo -> SDoc
-pprDests NoDestInfo = text "NoDestInfo"
-pprDests (DestInfo dsts) = brackets (hsep (map pprCLabel dsts))