fmtAsmLbl,
exactLog2,
- stixFor_stdout, stixFor_stderr, stixFor_stdin,
-
Instr(..), IF_ARCH_i386(Operand(..) COMMA,)
Cond(..),
Size(..),
#if i386_TARGET_ARCH
#endif
#if sparc_TARGET_ARCH
- , RI(..), riZero
+ RI(..), riZero, fpRelEA, moveSp, fPair
#endif
) where
import AbsCSyn ( MagicId(..) )
import AbsCUtils ( magicIdPrimRep )
import CLabel ( CLabel, isAsmTemp )
-import Const ( mkMachInt, Literal(..) )
+import Literal ( mkMachInt, Literal(..) )
import MachRegs ( stgReg, callerSaves, RegLoc(..),
Imm(..), Reg(..),
MachRegsAddr(..)
+# if sparc_TARGET_ARCH
+ ,fp, sp
+# endif
)
import PrimRep ( PrimRep(..) )
-import SMRep ( SMRep(..) )
-import Stix ( StixTree(..), StixReg(..), CodeSegment )
+import Stix ( StixTree(..), StixReg(..), CodeSegment, DestInfo(..) )
import Panic ( panic )
-import Char ( isDigit )
import GlaExts ( word2Int#, int2Word#, shiftRL#, and#, (/=#) )
-import Outputable ( text )
+import Outputable ( pprPanic, ppr )
+import IOExts ( trace )
\end{code}
\begin{code}
,{-otherwise-}
'.':'L':s
)
-
----------------------------
-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
-
-#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("stdin"
- ,IF_ARCH_sparc("__iob+0x0"{-probably OK...-}
- ,)))
-
-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+"++show (2*(``FILE_SIZE''::Int))
- ,IF_ARCH_i386("stderr"
- ,IF_ARCH_sparc("__iob+"++show (2*(``FILE_SIZE''::Int))
- ,)))
-#endif
-
\end{code}
% ----------------------------------------------------------------
-- the result is an Integer only because it's more convenient
sizeOf pr = case (primRepToSize pr) of
- IF_ARCH_alpha({B -> 1; BU -> 1; {-W -> 2; WU -> 2; L -> 4; SF -> 4;-} _ -> 8},)
+ IF_ARCH_alpha({B -> 1; BU -> 1; {-W -> 2; WU -> 2;-} L -> 4; {-SF -> 4;-} _ -> 8},)
IF_ARCH_sparc({B -> 1; BU -> 1; {-HW -> 2; HWU -> 2;-} W -> 4; {-D -> 8;-} F -> 4; DF -> 8},)
IF_ARCH_i386( {B -> 1; {-S -> 2;-} L -> 4; F -> 4; DF -> 8 },)
\end{code}
| BU
-- | W -- word (2 bytes): UNUSED
-- | WU -- : UNUSED
--- | L -- longword (4 bytes): UNUSED
+ | L -- longword (4 bytes)
| Q -- quadword (8 bytes)
-- | FF -- VAX F-style floating pt: UNUSED
-- | GF -- VAX G-style floating pt: UNUSED
| 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( B, IF_ARCH_sparc( BU,)))
+primRepToSize CharRep = IF_ARCH_alpha( L, IF_ARCH_i386( L, IF_ARCH_sparc( W ,)))
+primRepToSize Int8Rep = IF_ARCH_alpha( B, IF_ARCH_i386( B, IF_ARCH_sparc( B ,)))
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 ,)))
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 PrimPtrRep = 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 ForeignObjRep = IF_ARCH_alpha( Q, IF_ARCH_i386( L, IF_ARCH_sparc( W ,)))
+primRepToSize BCORep = 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 ThreadIdRep = IF_ARCH_alpha( Q, IF_ARCH_i386( L, IF_ARCH_sparc( W ,)))
+-- SUP: Wrong!!! Only for testing the rest of the NCG
+primRepToSize Word64Rep = trace "primRepToSize: Word64Rep not handled" B
+primRepToSize Int64Rep = trace "primRepToSize: Int64Rep not handled" B
\end{code}
%************************************************************************
String -- the literal string
| DATA Size
[Imm]
+ | DELTA Int -- specify current stack offset for
+ -- benefit of subsequent passes
\end{code}
\begin{code}
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
| 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.
| 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
-- Jumping around.
- | JMP Operand -- target
+ | JMP DestInfo Operand -- possible dests, target
| JXX Cond CLabel -- target
| CALL Imm
ffree_before_nonlocal_transfers insn
= case insn of
- CALL _ -> [GFREE, insn]
- JMP (OpImm (ImmCLbl clbl)) | isAsmTemp clbl -> [insn]
- JMP _ -> [GFREE, insn]
- other -> [insn]
+ 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,
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;
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
| BI Cond Bool Imm -- cond, annul?, target
| BF Cond Bool Imm -- cond, annul?, target
- | JMP MachRegsAddr -- target
+ | JMP DestInfo MachRegsAddr -- target
| CALL Imm Int Bool -- target, args, terminal
data RI = RIReg Reg
riZero (RIImm (ImmInt 0)) = True
riZero (RIImm (ImmInteger 0)) = True
-riZero (RIReg (FixedReg ILIT(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}