summaryrefslogtreecommitdiff
path: root/ghc/compiler/nativeGen/MachMisc.lhs
diff options
context:
space:
mode:
authorsimonmar <unknown>2004-08-13 13:11:23 +0000
committersimonmar <unknown>2004-08-13 13:11:23 +0000
commit423d477bfecd490de1449c59325c8776f91d7aac (patch)
tree2fe481e38a21be66b17539de24a4fe56daf80642 /ghc/compiler/nativeGen/MachMisc.lhs
parent553e90d9a32ee1b1809430f260c401cc4169c6c7 (diff)
downloadhaskell-423d477bfecd490de1449c59325c8776f91d7aac.tar.gz
[project @ 2004-08-13 13:04:50 by simonmar]
Merge backend-hacking-branch onto HEAD. Yay!
Diffstat (limited to 'ghc/compiler/nativeGen/MachMisc.lhs')
-rw-r--r--ghc/compiler/nativeGen/MachMisc.lhs789
1 files changed, 0 insertions, 789 deletions
diff --git a/ghc/compiler/nativeGen/MachMisc.lhs b/ghc/compiler/nativeGen/MachMisc.lhs
deleted file mode 100644
index a641a8a327..0000000000
--- a/ghc/compiler/nativeGen/MachMisc.lhs
+++ /dev/null
@@ -1,789 +0,0 @@
-%
-% (c) The AQUA Project, Glasgow University, 1993-1998
-%
-\section[MachMisc]{Description of various machine-specific things}
-
-\begin{code}
-#include "nativeGen/NCG.h"
-
-module MachMisc (
-
- primRepToSize,
-
- eXTRA_STK_ARGS_HERE,
-
- volatileSaves, volatileRestores,
-
- targetMaxDouble, targetMaxInt, targetMinDouble, targetMinInt,
-
- underscorePrefix,
- fmtAsmLbl,
- exactLog2,
-
- Instr(..), IF_ARCH_i386(Operand(..) COMMA,)
- Cond(..),
- Size(..),
- IF_ARCH_i386(i386_insert_ffrees COMMA,)
-
-#if alpha_TARGET_ARCH
- , RI(..)
-#endif
-#if i386_TARGET_ARCH
-#endif
-#if sparc_TARGET_ARCH
- RI(..), riZero, fpRelEA, moveSp, fPair
-#endif
-#if powerpc_TARGET_ARCH
- , RI(..)
- , condUnsigned, condToSigned
-#endif
- ) where
-
-#include "HsVersions.h"
-#include "../includes/config.h"
-
-import AbsCSyn ( MagicId(..) )
-import AbsCUtils ( magicIdPrimRep )
-import CLabel ( CLabel, isAsmTemp )
-import Literal ( mkMachInt, Literal(..) )
-import MachRegs ( callerSaves,
- get_MagicId_addr, get_MagicId_reg_or_addr,
- Imm(..), Reg(..), MachRegsAddr(..)
-# if sparc_TARGET_ARCH
- ,fp, sp
-# endif
- )
-import PrimRep ( PrimRep(..) )
-import Stix ( StixStmt(..), StixExpr(..), StixReg(..),
- CodeSegment, DestInfo(..) )
-import Panic ( panic )
-import Outputable ( pprPanic, ppr, showSDoc )
-import Config ( cLeadingUnderscore )
-import FastTypes
-import FastString
-
-import GLAEXTS
-import TRACE ( trace )
-
-import Maybes ( mapCatMaybes )
-\end{code}
-
-\begin{code}
-underscorePrefix :: Bool -- leading underscore on assembler labels?
-underscorePrefix = (cLeadingUnderscore == "YES")
-
----------------------------
-fmtAsmLbl :: String -> String -- for formatting labels
-
-fmtAsmLbl s
- {- The alpha assembler likes temporary labels to look like $L123
- instead of L123. (Don't toss the L, because then Lf28
- turns into $f28.)
- -}
- = IF_ARCH_alpha(
- '$' : s
- ,{-otherwise-}
- '.':'L':s
- )
-\end{code}
-
-% ----------------------------------------------------------------
-
-We (allegedly) put the first six C-call arguments in registers;
-where do we start putting the rest of them?
-\begin{code}
-eXTRA_STK_ARGS_HERE :: Int
-eXTRA_STK_ARGS_HERE
- = IF_ARCH_alpha(0, IF_ARCH_i386(23{-6x4bytes-}, IF_ARCH_sparc(23,
- IF_ARCH_powerpc( IF_OS_darwin(24,8{-SVR4 ABI: Linux-}), ???))))
-\end{code}
-
-% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
-Now the volatile saves and restores. We add the basic guys to the
-list of ``user'' registers provided. Note that there are more basic
-registers on the restore list, because some are reloaded from
-constants.
-
-(@volatileRestores@ used only for wrapper-hungry PrimOps.)
-
-\begin{code}
-volatileSaves, volatileRestores :: [MagicId] -> [StixStmt]
-
-volatileSaves = volatileSavesOrRestores True
-volatileRestores = volatileSavesOrRestores False
-
-save_cands = [BaseReg,Sp,SpLim,Hp,HpLim]
-restore_cands = save_cands
-
-volatileSavesOrRestores do_saves vols
- = mapCatMaybes mkCode vols
- where
- mkCode mid
- | case mid of { BaseReg -> True; _ -> False }
- = panic "volatileSavesOrRestores:BaseReg"
- | not (callerSaves mid)
- = Nothing
- | otherwise -- must be callee-saves ...
- = case get_MagicId_reg_or_addr mid of
- -- If stored in BaseReg, we ain't interested
- Right baseRegAddr
- -> Nothing
- Left (RealReg rrno)
- -- OK, it's callee-saves, and in a real reg (rrno).
- -- We have to cook up some transfer code.
- {- Note that the use of (StixMagicId mid) here is a bit subtle.
- Here, we only create those for MagicIds which are stored in
- a real reg on this arch -- the preceding case on the result
- of get_MagicId_reg_or_addr guarantees this. Later, when
- selecting insns, that means these assignments are sure to turn
- into real reg-to-mem or mem-to-reg moves, rather than being
- pointless moves from some address in the reg-table
- back to itself.-}
- | do_saves
- -> Just (StAssignMem rep addr
- (StReg (StixMagicId mid)))
- | otherwise
- -> Just (StAssignReg rep (StixMagicId mid)
- (StInd rep addr))
- where
- rep = magicIdPrimRep mid
- addr = get_MagicId_addr mid
-\end{code}
-
-% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
-Obviously slightly weedy
-(Note that the floating point values aren't terribly important.)
-ToDo: Fix!(JSM)
-\begin{code}
-targetMinDouble = MachDouble (-1.7976931348623157e+308)
-targetMaxDouble = MachDouble (1.7976931348623157e+308)
-targetMinInt = mkMachInt (-2147483648)
-targetMaxInt = mkMachInt 2147483647
-\end{code}
-
-% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
-This algorithm for determining the $\log_2$ of exact powers of 2 comes
-from GCC. It requires bit manipulation primitives, and we use GHC
-extensions. Tough.
-
-\begin{code}
-w2i x = word2Int# x
-i2w x = int2Word# x
-
-exactLog2 :: Integer -> Maybe Integer
-exactLog2 x
- = if (x <= 0 || x >= 2147483648) then
- Nothing
- else
- case iUnbox (fromInteger x) of { x# ->
- if (w2i ((i2w x#) `and#` (i2w (0# -# x#))) /=# x#) then
- Nothing
- else
- Just (toInteger (iBox (pow2 x#)))
- }
- where
- pow2 x# | x# ==# 1# = 0#
- | otherwise = 1# +# pow2 (w2i (i2w x# `shiftRL#` 1#))
-\end{code}
-
-% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
-\begin{code}
-data Cond
-#if alpha_TARGET_ARCH
- = ALWAYS -- For BI (same as BR)
- | EQQ -- For CMP and BI (NB: "EQ" is a 1.3 Prelude name)
- | GE -- For BI only
- | GTT -- For BI only (NB: "GT" is a 1.3 Prelude name)
- | LE -- For CMP and BI
- | LTT -- For CMP and BI (NB: "LT" is a 1.3 Prelude name)
- | NE -- For BI only
- | NEVER -- For BI (null instruction)
- | ULE -- For CMP only
- | ULT -- For CMP only
-#endif
-#if i386_TARGET_ARCH
- = ALWAYS -- What's really used? ToDo
- | EQQ
- | GE
- | GEU
- | GTT
- | GU
- | LE
- | LEU
- | LTT
- | LU
- | NE
- | NEG
- | POS
- | CARRY
- | OFLO
-#endif
-#if sparc_TARGET_ARCH
- = ALWAYS -- What's really used? ToDo
- | EQQ
- | GE
- | GEU
- | GTT
- | GU
- | LE
- | LEU
- | LTT
- | LU
- | NE
- | NEG
- | NEVER
- | POS
- | VC
- | VS
-#endif
-#if powerpc_TARGET_ARCH
- = ALWAYS
- | EQQ
- | GE
- | GEU
- | GTT
- | GU
- | LE
- | LEU
- | LTT
- | LU
- | NE
-#endif
- deriving Eq -- to make an assertion work
-\end{code}
-
-\begin{code}
-data Size
-#if alpha_TARGET_ARCH
- = B -- byte
- | Bu
--- | W -- word (2 bytes): UNUSED
--- | Wu -- : UNUSED
- | L -- longword (4 bytes)
- | Q -- quadword (8 bytes)
--- | FF -- VAX F-style floating pt: UNUSED
--- | GF -- VAX G-style floating pt: UNUSED
--- | DF -- VAX D-style floating pt: UNUSED
--- | SF -- IEEE single-precision floating pt: UNUSED
- | TF -- IEEE double-precision floating pt
-#endif
-#if i386_TARGET_ARCH
- = B -- byte (signed)
- | Bu -- byte (unsigned)
- | W -- word (signed)
- | Wu -- word (unsigned)
- | L -- longword (signed)
- | Lu -- longword (unsigned)
- | 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 || powerpc_TARGET_ARCH
- = B -- byte (signed)
- | Bu -- byte (unsigned)
- | H -- halfword (signed, 2 bytes)
- | Hu -- halfword (unsigned, 2 bytes)
- | W -- word (4 bytes)
- | F -- IEEE single-precision floating pt
- | DF -- IEEE single-precision floating pt
-#endif
-
-primRepToSize :: PrimRep -> Size
-
-primRepToSize PtrRep = IF_ARCH_alpha(Q, IF_ARCH_i386(L, IF_ARCH_sparc(W, IF_ARCH_powerpc(W, ))))
-primRepToSize CodePtrRep = IF_ARCH_alpha(Q, IF_ARCH_i386(L, IF_ARCH_sparc(W, IF_ARCH_powerpc(W, ))))
-primRepToSize DataPtrRep = IF_ARCH_alpha(Q, IF_ARCH_i386(L, IF_ARCH_sparc(W, IF_ARCH_powerpc(W, ))))
-primRepToSize RetRep = IF_ARCH_alpha(Q, IF_ARCH_i386(L, IF_ARCH_sparc(W, IF_ARCH_powerpc(W, ))))
-primRepToSize CostCentreRep = IF_ARCH_alpha(Q, IF_ARCH_i386(L, IF_ARCH_sparc(W, IF_ARCH_powerpc(W, ))))
-primRepToSize CharRep = IF_ARCH_alpha(L, IF_ARCH_i386(L, IF_ARCH_sparc(W, IF_ARCH_powerpc(W, ))))
-
-primRepToSize Int8Rep = IF_ARCH_alpha(B, IF_ARCH_i386(B, IF_ARCH_sparc(B, IF_ARCH_powerpc(B, ))))
-primRepToSize Int16Rep = IF_ARCH_alpha(err,IF_ARCH_i386(W, IF_ARCH_sparc(H, IF_ARCH_powerpc(H, ))))
- where err = primRepToSize_fail "Int16Rep"
-primRepToSize Int32Rep = IF_ARCH_alpha(L, IF_ARCH_i386(L, IF_ARCH_sparc(W, IF_ARCH_powerpc(W, ))))
-primRepToSize Word8Rep = IF_ARCH_alpha(Bu, IF_ARCH_i386(Bu, IF_ARCH_sparc(Bu, IF_ARCH_powerpc(Bu, ))))
-primRepToSize Word16Rep = IF_ARCH_alpha(err,IF_ARCH_i386(Wu, IF_ARCH_sparc(Hu, IF_ARCH_powerpc(Hu, ))))
- where err = primRepToSize_fail "Word16Rep"
-primRepToSize Word32Rep = IF_ARCH_alpha(L, IF_ARCH_i386(Lu, IF_ARCH_sparc(W, IF_ARCH_powerpc(W, ))))
-
-primRepToSize IntRep = IF_ARCH_alpha(Q, IF_ARCH_i386(L, IF_ARCH_sparc(W, IF_ARCH_powerpc(W, ))))
-primRepToSize WordRep = IF_ARCH_alpha(Q, IF_ARCH_i386(L, IF_ARCH_sparc(W, IF_ARCH_powerpc(W, ))))
-primRepToSize AddrRep = IF_ARCH_alpha(Q, IF_ARCH_i386(L, IF_ARCH_sparc(W, IF_ARCH_powerpc(W, ))))
-primRepToSize FloatRep = IF_ARCH_alpha(TF, IF_ARCH_i386(F, IF_ARCH_sparc(F, IF_ARCH_powerpc(F, ))))
-primRepToSize DoubleRep = IF_ARCH_alpha(TF, IF_ARCH_i386(DF, IF_ARCH_sparc(DF, IF_ARCH_powerpc(DF, ))))
-primRepToSize StablePtrRep = IF_ARCH_alpha(Q, IF_ARCH_i386(L, IF_ARCH_sparc(W, IF_ARCH_powerpc(W, ))))
-
-primRepToSize Word64Rep = primRepToSize_fail "Word64Rep"
-primRepToSize Int64Rep = primRepToSize_fail "Int64Rep"
-primRepToSize other = primRepToSize_fail (showSDoc (ppr other))
-
-primRepToSize_fail str
- = error ("ERROR: MachMisc.primRepToSize: cannot handle `" ++ str ++ "'.\n\t"
- ++ "Workaround: use -fvia-C.\n\t"
- ++ "Perhaps you should report it as a GHC bug,\n\t"
- ++ "to glasgow-haskell-bugs@haskell.org.")
-\end{code}
-
-%************************************************************************
-%* *
-\subsection{Machine's assembly language}
-%* *
-%************************************************************************
-
-We have a few common ``instructions'' (nearly all the pseudo-ops) but
-mostly all of @Instr@ is machine-specific.
-
-\begin{code}
-data Instr
- = COMMENT FastString -- comment pseudo-op
- | SEGMENT CodeSegment -- {data,text} segment pseudo-op
- | LABEL CLabel -- global label pseudo-op
- | ASCII Bool -- True <=> needs backslash conversion
- String -- the literal string
- | DATA Size
- [Imm]
- | DELTA Int -- specify current stack offset for
- -- benefit of subsequent passes
-\end{code}
-
-\begin{code}
-#if alpha_TARGET_ARCH
-
--- data Instr continues...
-
--- Loads and stores.
-
- | LD Size Reg MachRegsAddr -- size, dst, src
- | LDA Reg MachRegsAddr -- dst, src
- | LDAH Reg MachRegsAddr -- dst, src
- | LDGP Reg MachRegsAddr -- dst, src
- | LDI Size Reg Imm -- size, dst, src
- | ST Size Reg MachRegsAddr -- size, src, dst
-
--- Int Arithmetic.
-
- | CLR Reg -- dst
- | ABS Size RI Reg -- size, src, dst
- | NEG Size Bool RI Reg -- size, overflow, src, dst
- | ADD Size Bool Reg RI Reg -- size, overflow, src, src, dst
- | SADD Size Size Reg RI Reg -- size, scale, src, src, dst
- | SUB Size Bool Reg RI Reg -- size, overflow, src, src, dst
- | SSUB Size Size Reg RI Reg -- size, scale, src, src, dst
- | MUL Size Bool Reg RI Reg -- size, overflow, src, src, dst
- | DIV Size Bool Reg RI Reg -- size, unsigned, src, src, dst
- | REM Size Bool Reg RI Reg -- size, unsigned, src, src, dst
-
--- Simple bit-twiddling.
-
- | NOT RI Reg
- | AND Reg RI Reg
- | ANDNOT Reg RI Reg
- | OR Reg RI Reg
- | ORNOT Reg RI Reg
- | XOR Reg RI Reg
- | XORNOT Reg RI Reg
- | SLL Reg RI Reg
- | SRL Reg RI Reg
- | SRA Reg RI Reg
-
- | ZAP Reg RI Reg
- | ZAPNOT Reg RI Reg
-
- | NOP
-
--- Comparison
-
- | CMP Cond Reg RI Reg
-
--- Float Arithmetic.
-
- | FCLR Reg
- | FABS Reg Reg
- | FNEG Size Reg Reg
- | FADD Size Reg Reg Reg
- | FDIV Size Reg Reg Reg
- | FMUL Size Reg Reg Reg
- | FSUB Size Reg Reg Reg
- | CVTxy Size Size Reg Reg
- | FCMP Size Cond Reg Reg Reg
- | FMOV Reg Reg
-
--- Jumping around.
-
- | BI Cond Reg Imm
- | BF Cond Reg Imm
- | BR Imm
- | JMP Reg MachRegsAddr Int
- | BSR Imm Int
- | JSR Reg MachRegsAddr Int
-
--- Alpha-specific pseudo-ops.
-
- | FUNBEGIN CLabel
- | FUNEND CLabel
-
-data RI
- = RIReg Reg
- | RIImm Imm
-
-#endif /* alpha_TARGET_ARCH */
-\end{code}
-
-Intel, in their infinite wisdom, selected a stack model for floating
-point registers on x86. That might have made sense back in 1979 --
-nowadays we can see it for the nonsense it really is. A stack model
-fits poorly with the existing nativeGen infrastructure, which assumes
-flat integer and FP register sets. Prior to this commit, nativeGen
-could not generate correct x86 FP code -- to do so would have meant
-somehow working the register-stack paradigm into the register
-allocator and spiller, which sounds very difficult.
-
-We have decided to cheat, and go for a simple fix which requires no
-infrastructure modifications, at the expense of generating ropey but
-correct FP code. All notions of the x86 FP stack and its insns have
-been removed. Instead, we pretend (to the instruction selector and
-register allocator) that x86 has six floating point registers, %fake0
-.. %fake5, which can be used in the usual flat manner. We further
-claim that x86 has floating point instructions very similar to SPARC
-and Alpha, that is, a simple 3-operand register-register arrangement.
-Code generation and register allocation proceed on this basis.
-
-When we come to print out the final assembly, our convenient fiction
-is converted to dismal reality. Each fake instruction is
-independently converted to a series of real x86 instructions.
-%fake0 .. %fake5 are mapped to %st(0) .. %st(5). To do reg-reg
-arithmetic operations, the two operands are pushed onto the top of the
-FP stack, the operation done, and the result copied back into the
-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!
-
-LATER (10 Nov 2000): idiv gives problems with the register spiller,
-because the spiller is simpleminded and because idiv has fixed uses of
-%eax and %edx. Rather than make the spiller cleverer, we do away with
-idiv, and instead have iquot and irem fake (integer) insns, which have
-no operand register constraints -- ie, they behave like add, sub, mul.
-The printer-outer transforms them to a sequence of real insns which does
-the Right Thing (tm). As with the FP stuff, this gives ropey code,
-but we don't care, since it doesn't get used much. We hope.
-
-\begin{code}
-#if i386_TARGET_ARCH
-
--- data Instr continues...
-
--- Moves.
-
- | MOV Size Operand Operand
- | 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 :-)
-
- | LEA Size Operand Operand
-
--- Int Arithmetic.
-
- | ADD Size Operand Operand
- | SUB Size Operand Operand
- | IMUL Size Operand Operand -- signed int mul
- | MUL Size Operand Operand -- unsigned int mul
- | IMUL64 Reg Reg -- 32 x 32 -> 64 signed mul
- -- operand1:operand2 := (operand1[31:0] *signed operand2[31:0])
-
--- Quotient and remainder. SEE comment above -- these are not
--- real x86 insns; instead they are expanded when printed
--- into a sequence of real insns.
-
- | IQUOT Size Operand Operand -- signed quotient
- | IREM Size Operand Operand -- signed remainder
- | QUOT Size Operand Operand -- unsigned quotient
- | REM Size Operand Operand -- unsigned remainder
-
--- Simple bit-twiddling.
-
- | AND Size Operand Operand
- | OR Size Operand Operand
- | XOR Size Operand Operand
- | NOT Size Operand
- | NEGI Size Operand -- NEG instruction (name clash with Cond)
- | 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.
-
--- 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)
-
- | GFTOI Reg Reg -- src(fpreg), dst(intreg)
- | GDTOI Reg Reg -- src(fpreg), dst(intreg)
-
- | GITOF Reg Reg -- src(intreg), dst(fpreg)
- | GITOD Reg Reg -- src(intreg), dst(fpreg)
-
- | GADD Size Reg Reg Reg -- src1, src2, dst
- | GDIV Size Reg Reg Reg -- src1, src2, dst
- | GSUB Size Reg Reg Reg -- src1, src2, dst
- | GMUL Size Reg Reg Reg -- src1, src2, dst
-
- -- FP compare. Cond must be `elem` [EQQ, NE, LE, LTT, GE, GTT]
- -- Compare src1 with src2; set the Zero flag iff the numbers are
- -- comparable and the comparison is True. Subsequent code must
- -- test the %eflags zero flag regardless of the supplied Cond.
- | GCMP Cond Reg Reg -- src1, src2
-
- | 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
- | CMP Size Operand Operand
- | SETCC Cond Operand
-
--- Stack Operations.
-
- | PUSH Size Operand
- | POP Size Operand
- | PUSHA
- | POPA
-
--- Jumping around.
-
- | JMP DestInfo Operand -- possible dests, target
- | JXX Cond CLabel -- target
- | CALL (Either Imm Reg)
-
--- Other things.
-
- | CLTD -- sign extend %eax into %edx:%eax
-
-data Operand
- = OpReg Reg -- register
- | 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]
- -- Jumps to immediate labels are local
- JMP _ (OpImm (ImmCLbl clbl)) | isAsmTemp clbl -> [insn]
- -- If a jump mentions dests, it is a local jump thru
- -- a case table.
- JMP (DestInfo _) _ -> [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;
- 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;
- GFREE -> panic "is_G_instr: GFREE (!)"
- other -> False
-
-#endif /* i386_TARGET_ARCH */
-\end{code}
-
-\begin{code}
-#if sparc_TARGET_ARCH
-
--- data Instr continues...
-
--- Loads and stores.
-
- | LD Size MachRegsAddr Reg -- size, src, dst
- | ST Size Reg MachRegsAddr -- size, src, dst
-
--- Int Arithmetic.
-
- | ADD Bool Bool Reg RI Reg -- x?, cc?, src1, src2, dst
- | SUB Bool Bool Reg RI Reg -- x?, cc?, src1, src2, dst
- | UMUL Bool Reg RI Reg -- cc?, src1, src2, dst
- | SMUL Bool Reg RI Reg -- cc?, src1, src2, dst
- | RDY Reg -- move contents of Y register to reg
-
--- Simple bit-twiddling.
-
- | AND Bool Reg RI Reg -- cc?, src1, src2, dst
- | ANDN Bool Reg RI Reg -- cc?, src1, src2, dst
- | OR Bool Reg RI Reg -- cc?, src1, src2, dst
- | ORN Bool Reg RI Reg -- cc?, src1, src2, dst
- | XOR Bool Reg RI Reg -- cc?, src1, src2, dst
- | XNOR Bool Reg RI Reg -- cc?, src1, src2, dst
- | SLL Reg RI Reg -- src1, src2, dst
- | SRL Reg RI Reg -- src1, src2, dst
- | SRA Reg RI Reg -- src1, src2, dst
- | SETHI Imm Reg -- src, dst
- | NOP -- Really SETHI 0, %g0, but worth an alias
-
--- Float Arithmetic.
-
--- Note that we cheat by treating F{ABS,MOV,NEG} of doubles as single instructions
--- right up until we spit them out.
-
- | FABS Size Reg Reg -- src dst
- | FADD Size Reg Reg Reg -- src1, src2, dst
- | FCMP Bool Size Reg Reg -- exception?, src1, src2, dst
- | FDIV Size Reg Reg Reg -- src1, src2, dst
- | FMOV Size Reg Reg -- src, dst
- | FMUL Size Reg Reg Reg -- src1, src2, dst
- | FNEG Size Reg Reg -- src, dst
- | FSQRT Size Reg Reg -- src, dst
- | FSUB Size Reg Reg Reg -- src1, src2, dst
- | FxTOy Size Size Reg Reg -- src, dst
-
--- Jumping around.
-
- | BI Cond Bool Imm -- cond, annul?, target
- | BF Cond Bool Imm -- cond, annul?, target
-
- | JMP DestInfo MachRegsAddr -- target
- | CALL (Either Imm Reg) Int Bool -- target, args, terminal
-
-data RI = RIReg Reg
- | RIImm Imm
-
-riZero :: RI -> Bool
-
-riZero (RIImm (ImmInt 0)) = True
-riZero (RIImm (ImmInteger 0)) = True
-riZero (RIReg (RealReg 0)) = True
-riZero _ = False
-
--- Calculate the effective address which would be used by the
--- corresponding fpRel sequence. fpRel is in MachRegs.lhs,
--- 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
-
--- 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
-
--- Produce the second-half-of-a-double register given the first half.
-fPair :: Reg -> Reg
-fPair (RealReg n) | n >= 32 && n `mod` 2 == 0 = RealReg (n+1)
-fPair other = pprPanic "fPair(sparc NCG)" (ppr other)
-#endif /* sparc_TARGET_ARCH */
-\end{code}
-
-\begin{code}
-#ifdef powerpc_TARGET_ARCH
--- data Instr continues...
-
--- Loads and stores.
-
- | LD Size Reg MachRegsAddr -- Load size, dst, src
- | ST Size Reg MachRegsAddr -- Store size, src, dst
- | STU Size Reg MachRegsAddr -- Store with Update size, src, dst
- | LIS Reg Imm -- Load Immediate Shifted dst, src
- | LI Reg Imm -- Load Immediate dst, src
- | MR Reg Reg -- Move Register dst, src -- also for fmr
-
- | CMP Size Reg RI --- size, src1, src2
- | CMPL Size Reg RI --- size, src1, src2
-
- | BCC Cond CLabel
- | MTCTR Reg
- | BCTR DestInfo
- | BL Imm [Reg] -- with list of argument regs
- | BCTRL [Reg]
-
- | ADD Reg Reg RI -- dst, src1, src2
- | SUBF Reg Reg Reg -- dst, src1, src2 ; dst = src2 - src1
- | MULLW Reg Reg RI
- | DIVW Reg Reg Reg
- | DIVWU Reg Reg Reg
-
- | AND Reg Reg RI -- dst, src1, src2
- | OR Reg Reg RI -- dst, src1, src2
- | XOR Reg Reg RI -- dst, src1, src2
- | XORIS Reg Reg Imm -- XOR Immediate Shifted dst, src1, src2
-
- | NEG Reg Reg
- | NOT Reg Reg
-
- | SLW Reg Reg RI -- shift left word
- | SRW Reg Reg RI -- shift right word
- | SRAW Reg Reg RI -- shift right arithmetic word
-
- | FADD Size Reg Reg Reg
- | FSUB Size Reg Reg Reg
- | FMUL Size Reg Reg Reg
- | FDIV Size Reg Reg Reg
- | FNEG Reg Reg -- negate is the same for single and double prec.
-
- | FCMP Reg Reg
-
- | FCTIWZ Reg Reg -- convert to integer word
- -- (but destination is a FP register)
-
-data RI = RIReg Reg
- | RIImm Imm
-
-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 */
-\end{code}
-