%
-% (c) The AQUA Project, Glasgow University, 1993-1996
+% (c) The AQUA Project, Glasgow University, 1993-1998
%
\section[MachMisc]{Description of various machine-specific things}
\begin{code}
-#include "HsVersions.h"
#include "nativeGen/NCG.h"
module MachMisc (
- fixedHdrSizeInWords, varHdrSizeInWords,
- charLikeSize, intLikeSize, mutHS, dataHS,
sizeOf, primRepToSize,
eXTRA_STK_ARGS_HERE,
volatileSaves, volatileRestores,
- storageMgrInfo, smCAFlist, smOldLim, smOldMutables,
- smStablePtrTable,
-
targetMaxDouble, targetMaxInt, targetMinDouble, targetMinInt,
underscorePrefix,
fmtAsmLbl,
- cvtLitLit,
exactLog2,
+ stixFor_stdout, stixFor_stderr, stixFor_stdin,
+
Instr(..), IF_ARCH_i386(Operand(..) COMMA,)
Cond(..),
Size(..)
#endif
) where
-IMP_Ubiq(){-uitous-}
-IMPORT_DELOOPER(AbsCLoop) ( fixedHdrSizeInWords, varHdrSizeInWords ) -- paranoia
-IMPORT_DELOOPER(NcgLoop) ( underscorePrefix, fmtAsmLbl ) -- paranoia
-IMPORT_1_3(Char(isDigit))
+#include "HsVersions.h"
+-- #include "config.h"
import AbsCSyn ( MagicId(..) )
import AbsCUtils ( magicIdPrimRep )
-import CmdLineOpts ( opt_SccProfilingOn )
-import Literal ( mkMachInt, Literal(..) )
+import CLabel ( CLabel )
+import Const ( mkMachInt, Literal(..) )
import MachRegs ( stgReg, callerSaves, RegLoc(..),
- Imm(..), Reg(..), Addr
+ Imm(..), Reg(..),
+ MachRegsAddr(..)
)
-import OrdList ( OrdList )
import PrimRep ( PrimRep(..) )
-import SMRep ( SMRep(..), SMSpecRepKind(..), SMUpdateKind(..) )
-import Stix ( StixTree(..), StixReg(..), sStLitLbl,
- CodeSegment
- )
-import Util ( panic )
+import SMRep ( SMRep(..) )
+import Stix ( StixTree(..), StixReg(..), CodeSegment )
+import Panic ( panic )
+import Char ( isDigit )
+import GlaExts ( word2Int#, int2Word#, shiftRL#, and#, (/=#) )
+import Outputable ( text )
\end{code}
\begin{code}
-underscorePrefix :: Bool -- leading underscore on labels?
-
-underscorePrefix
- = IF_ARCH_alpha(False
- ,{-else-} IF_ARCH_i386(
- IF_OS_linuxaout(True
- , IF_OS_freebsd(True
- , IF_OS_bsdi(True
- , {-otherwise-} False)))
- ,{-else-}IF_ARCH_sparc(
- IF_OS_sunos4(True, {-otherwise-} False)
- ,)))
+underscorePrefix :: Bool -- leading underscore on assembler labels?
+
+#ifdef LEADING_UNDERSCORE
+underscorePrefix = True
+#else
+underscorePrefix = False
+#endif
---------------------------
fmtAsmLbl :: String -> String -- for formatting labels
)
---------------------------
-cvtLitLit :: String -> String
+stixFor_stdout, stixFor_stderr, stixFor_stdin :: StixTree
+#if i386_TARGET_ARCH
+-- Linux glibc 2 / libc6
+stixFor_stdout = StInd PtrRep (StLitLbl (text "stdout"))
+stixFor_stderr = StInd PtrRep (StLitLbl (text "stderr"))
+stixFor_stdin = StInd PtrRep (StLitLbl (text "stdin"))
+#endif
+
+#if alpha_TARGET_ARCH
+stixFor_stdout = error "stixFor_stdout: not implemented for Alpha"
+stixFor_stderr = error "stixFor_stderr: not implemented for Alpha"
+stixFor_stdin = error "stixFor_stdin: not implemented for Alpha"
+#endif
+
+#if sparc_TARGET_ARCH
+stixFor_stdout = error "stixFor_stdout: not implemented for Sparc"
+stixFor_stderr = error "stixFor_stderr: not implemented for Sparc"
+stixFor_stdin = error "stixFor_stdin: not implemented for Sparc"
+#endif
--- ToDo: some kind of *careful* attention needed...
+#if 0
+Here's some old stuff from which it shouldn't be too hard to
+implement the above for Alpha/Sparc.
+
+cvtLitLit :: String -> String
+--
+-- Rather than relying on guessing, use FILE_SIZE to compute the
+-- _iob offsets.
+--
cvtLitLit "stdin" = IF_ARCH_alpha("_iob+0" {-probably OK...-}
- ,IF_ARCH_i386("_IO_stdin_"
+ ,IF_ARCH_i386("stdin"
,IF_ARCH_sparc("__iob+0x0"{-probably OK...-}
,)))
-cvtLitLit "stdout" = IF_ARCH_alpha("_iob+56"{-dodgy *at best*...-}
- ,IF_ARCH_i386("_IO_stdout_"
- ,IF_ARCH_sparc("__iob+0x14"{-dodgy *at best*...-}
+
+cvtLitLit "stdout" = IF_ARCH_alpha("_iob+"++show (``FILE_SIZE''::Int)
+ ,IF_ARCH_i386("stdout"
+ ,IF_ARCH_sparc("__iob+"++show (``FILE_SIZE''::Int)
,)))
-cvtLitLit "stderr" = IF_ARCH_alpha("_iob+112"{-dodgy *at best*...-}
- ,IF_ARCH_i386("_IO_stderr_"
- ,IF_ARCH_sparc("__iob+0x28"{-dodgy *at best*...-}
+cvtLitLit "stderr" = IF_ARCH_alpha("_iob+"++show (2*(``FILE_SIZE''::Int))
+ ,IF_ARCH_i386("stderr"
+ ,IF_ARCH_sparc("__iob+"++show (2*(``FILE_SIZE''::Int))
,)))
-cvtLitLit s
- | isHex s = s
- | otherwise = error ("Native code generator can't handle ``" ++ s ++ "''")
- where
- isHex ('0':'x':xs) = all isHexDigit xs
- isHex _ = False
- -- Now, where have I seen this before?
- isHexDigit c = isDigit c || c >= 'A' && c <= 'F' || c >= 'a' && c <= 'f'
+#endif
+
\end{code}
% ----------------------------------------------------------------
= IF_ARCH_alpha(0, IF_ARCH_i386(23{-6x4bytes-}, IF_ARCH_sparc(23,???)))
\end{code}
-% ----------------------------------------------------------------
-
-@fixedHdrSizeInWords@ and @varHdrSizeInWords@: these are not dependent
-on target architecture.
-\begin{code}
-fixedHdrSizeInWords :: Int
-
-fixedHdrSizeInWords
- = 1{-info ptr-} + profFHS + parFHS + tickyFHS
- -- obviously, we aren't taking non-sequential too seriously yet
- where
- profFHS = if opt_SccProfilingOn then 1 else 0
- parFHS = {-if PAR or GRAN then 1 else-} 0
- tickyFHS = {-if ticky ... then 1 else-} 0
-
-varHdrSizeInWords :: SMRep -> Int{-in words-}
-
-varHdrSizeInWords sm
- = case sm of
- StaticRep _ _ -> 0
- SpecialisedRep _ _ _ _ -> 0
- GenericRep _ _ _ -> 0
- BigTupleRep _ -> 1
- MuTupleRep _ -> 2 {- (1 + GC_MUT_RESERVED_WORDS) -}
- DataRep _ -> 1
- DynamicRep -> 2
- BlackHoleRep -> 0
- PhantomRep -> panic "MachMisc.varHdrSizeInWords:phantom"
-\end{code}
-
-% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
-Static closure sizes:
-\begin{code}
-charLikeSize, intLikeSize :: Int
-
-charLikeSize = blahLikeSize CharLikeRep
-intLikeSize = blahLikeSize IntLikeRep
-
-blahLikeSize blah
- = fromInteger (sizeOf PtrRep)
- * (fixedHdrSizeInWords + varHdrSizeInWords blahLikeRep + 1)
- where
- blahLikeRep = SpecialisedRep blah 0 1 SMNormalForm
-
---------
-mutHS, dataHS :: StixTree
-
-mutHS = blah_hs (MuTupleRep 0)
-dataHS = blah_hs (DataRep 0)
-
-blah_hs blah
- = StInt (toInteger words)
- where
- words = fixedHdrSizeInWords + varHdrSizeInWords blah
-\end{code}
-
% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Size of a @PrimRep@, in bytes.
\begin{code}
volatileSaves, volatileRestores :: [MagicId] -> [StixTree]
-save_cands = [BaseReg,SpA,SuA,SpB,SuB,Hp,HpLim,RetReg]
-restore_cands = save_cands ++ [StkStubReg,StdUpdRetVecReg]
+save_cands = [BaseReg,Sp,Su,SpLim,Hp,HpLim]
+restore_cands = save_cands
volatileSaves vols
= map save ((filter callerSaves) (save_cands ++ vols))
\begin{code}
targetMinDouble = MachDouble (-1.7976931348623157e+308)
targetMaxDouble = MachDouble (1.7976931348623157e+308)
-targetMinInt = mkMachInt (-2147483647)
+targetMinInt = mkMachInt (-2147483648)
targetMaxInt = mkMachInt 2147483647
\end{code}
% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-Storage manager nonsense. Note that the indices are dependent on
-the definition of the smInfo structure in SMinterface.lh
-
-\begin{code}
-storageMgrInfo, smCAFlist, smOldMutables, smOldLim :: StixTree
-
-storageMgrInfo = sStLitLbl SLIT("StorageMgrInfo")
-smCAFlist = StInd PtrRep (StIndex PtrRep storageMgrInfo (StInt SM_CAFLIST))
-smOldMutables = StInd PtrRep (StIndex PtrRep storageMgrInfo (StInt SM_OLDMUTABLES))
-smOldLim = StInd PtrRep (StIndex PtrRep storageMgrInfo (StInt SM_OLDLIM))
-smStablePtrTable = StInd PtrRep (StIndex PtrRep storageMgrInfo (StInt SM_STABLEPOINTERTABLE))
-\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
-i2w_s x = (x::Int#)
exactLog2 :: Integer -> Maybe Integer
exactLog2 x
Just (toInteger (I# (pow2 x#)))
}
where
- shiftr x y = shiftRA# x y
+ shiftr x y = shiftRL# x y
pow2 x# | x# ==# 1# = 0#
- | otherwise = 1# +# pow2 (w2i (i2w x# `shiftr` i2w_s 1#))
+ | otherwise = 1# +# pow2 (w2i (i2w x# `shiftr` 1#))
\end{code}
% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
primRepToSize DoubleRep = IF_ARCH_alpha( TF, IF_ARCH_i386( DF,IF_ARCH_sparc( DF,)))
primRepToSize ArrayRep = IF_ARCH_alpha( Q, IF_ARCH_i386( L, IF_ARCH_sparc( W ,)))
primRepToSize ByteArrayRep = IF_ARCH_alpha( Q, IF_ARCH_i386( L, IF_ARCH_sparc( W ,)))
+primRepToSize WeakPtrRep = IF_ARCH_alpha( Q, IF_ARCH_i386( L, IF_ARCH_sparc( W ,)))
+primRepToSize ForeignObjRep = IF_ARCH_alpha( Q, IF_ARCH_i386( L, IF_ARCH_sparc( W ,)))
primRepToSize StablePtrRep = IF_ARCH_alpha( Q, IF_ARCH_i386( L, IF_ARCH_sparc( W ,)))
-primRepToSize ForeignObjRep = IF_ARCH_alpha( Q, IF_ARCH_i386( L, IF_ARCH_sparc( W ,)))
\end{code}
%************************************************************************
-- Loads and stores.
- | LD Size Reg Addr -- size, dst, src
- | LDA Reg Addr -- dst, src
- | LDAH Reg Addr -- dst, src
- | LDGP Reg Addr -- dst, src
- | LDI Size Reg Imm -- size, dst, src
- | ST Size Reg Addr -- size, src, dst
+ | 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.
| BI Cond Reg Imm
| BF Cond Reg Imm
| BR Imm
- | JMP Reg Addr Int
+ | JMP Reg MachRegsAddr Int
| BSR Imm Int
- | JSR Reg Addr Int
+ | JSR Reg MachRegsAddr Int
-- Alpha-specific pseudo-ops.
| 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
- | SAR Size Operand Operand -- 1st operand must be an Imm
- | SHR Size Operand Operand -- 1st operand must be an Imm
+ | 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
| NOP
-- Float Arithmetic. -- ToDo for 386
--- Note that we cheat by treating F{ABS,MOV,NEG} of doubles as single instructions
+-- Note that we cheat by treating G{ABS,MOV,NEG} of doubles as single instructions
-- right up until we spit them out.
- | SAHF -- stores ah into flags
- | FABS
- | FADD Size Operand -- src
- | FADDP
- | FIADD Size Addr -- src
- | FCHS
- | FCOM Size Operand -- src
- | FCOS
- | FDIV Size Operand -- src
- | FDIVP
- | FIDIV Size Addr -- src
- | FDIVR Size Operand -- src
- | FDIVRP
- | FIDIVR Size Addr -- src
- | FICOM Size Addr -- src
- | FILD Size Addr Reg -- src, dst
- | FIST Size Addr -- dst
- | FLD Size Operand -- src
- | FLD1
- | FLDZ
- | FMUL Size Operand -- src
- | FMULP
- | FIMUL Size Addr -- src
- | FRNDINT
- | FSIN
- | FSQRT
- | FST Size Operand -- dst
- | FSTP Size Operand -- dst
- | FSUB Size Operand -- src
- | FSUBP
- | FISUB Size Addr -- src
- | FSUBR Size Operand -- src
- | FSUBRP
- | FISUBR Size Addr -- src
- | FTST
- | FCOMP Size Operand -- src
- | FUCOMPP
- | FXCH
- | FNSTSW
- | FNOP
+ -- all the 3-operand fake fp insns are src1 src2 dst
+ -- and furthermore are constrained to be fp regs only.
+ | GMOV Reg Reg -- src(fpreg), dst(fpreg)
+ | GLD Size MachRegsAddr Reg -- src, dst(fpreg)
+ | GST Size Reg MachRegsAddr -- src(fpreg), dst
+
+ | GFTOD Reg Reg -- src(fpreg), dst(fpreg)
+ | GFTOI Reg Reg -- src(fpreg), dst(intreg)
+
+ | GDTOF Reg Reg -- src(fpreg), dst(fpreg)
+ | 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
+
+ | GCMP Size Reg Reg -- src1, src2
+
+ | GABS Size Reg Reg -- src, dst
+ | GNEG Size Reg Reg -- src, dst
+ | GSQRT Size Reg Reg -- src, dst
-- Comparison
| PUSH Size Operand
| POP Size Operand
+ | PUSHA
+ | POPA
-- Jumping around.
| CLTD -- sign extend %eax into %edx:%eax
data Operand
- = OpReg Reg -- register
- | OpImm Imm -- immediate value
- | OpAddr Addr -- memory reference
+ = OpReg Reg -- register
+ | OpImm Imm -- immediate value
+ | OpAddr MachRegsAddr -- memory reference
#endif {- i386_TARGET_ARCH -}
\end{code}
-- Loads and stores.
- | LD Size Addr Reg -- size, src, dst
- | ST Size Reg Addr -- size, src, dst
+ | LD Size MachRegsAddr Reg -- size, src, dst
+ | ST Size Reg MachRegsAddr -- size, src, dst
-- Int Arithmetic.
| BI Cond Bool Imm -- cond, annul?, target
| BF Cond Bool Imm -- cond, annul?, target
- | JMP Addr -- target
+ | JMP MachRegsAddr -- target
| CALL Imm Int Bool -- target, args, terminal
data RI = RIReg Reg