2 % (c) The AQUA Project, Glasgow University, 1993-1996
4 \section[MachMisc]{Description of various machine-specific things}
7 #include "HsVersions.h"
8 #include "nativeGen/NCG.h"
12 fixedHdrSizeInWords, varHdrSizeInWords,
13 charLikeSize, intLikeSize, mutHS, dataHS,
14 sizeOf, primRepToSize,
18 volatileSaves, volatileRestores,
20 storageMgrInfo, smCAFlist, smOldLim, smOldMutables,
23 targetMaxDouble, targetMaxInt, targetMinDouble, targetMinInt,
30 Instr(..), IF_ARCH_i386(Operand(..) COMMA,)
45 IMPORT_DELOOPER(AbsCLoop) ( fixedHdrSizeInWords, varHdrSizeInWords ) -- paranoia
46 IMPORT_DELOOPER(NcgLoop) ( underscorePrefix, fmtAsmLbl ) -- paranoia
47 IMPORT_1_3(Char(isDigit))
49 import AbsCSyn ( MagicId(..) )
50 import AbsCUtils ( magicIdPrimRep )
51 import CmdLineOpts ( opt_SccProfilingOn )
52 import Literal ( mkMachInt, Literal(..) )
53 import MachRegs ( stgReg, callerSaves, RegLoc(..),
54 Imm(..), Reg(..), Addr
56 import OrdList ( OrdList )
57 import PrimRep ( PrimRep(..) )
58 import SMRep ( SMRep(..), SMSpecRepKind(..), SMUpdateKind(..) )
59 import Stix ( StixTree(..), StixReg(..), sStLitLbl,
66 underscorePrefix :: Bool -- leading underscore on labels?
70 ,{-else-} IF_ARCH_i386(
74 , {-otherwise-} False)))
75 ,{-else-}IF_ARCH_sparc(
76 IF_OS_sunos4(True, {-otherwise-} False)
79 ---------------------------
80 fmtAsmLbl :: String -> String -- for formatting labels
84 {- The alpha assembler likes temporary labels to look like $L123
85 instead of L123. (Don't toss the L, because then Lf28
93 ---------------------------
94 cvtLitLit :: String -> String
97 -- Rather than relying on guessing, use FILE_SIZE to compute the
100 cvtLitLit "stdin" = IF_ARCH_alpha("_iob+0" {-probably OK...-}
101 ,IF_ARCH_i386("_IO_stdin_"
102 ,IF_ARCH_sparc("__iob+0x0"{-probably OK...-}
105 cvtLitLit "stdout" = IF_ARCH_alpha("_iob+"++show (``FILE_SIZE''::Int)
106 ,IF_ARCH_i386("_IO_stdout_"
107 ,IF_ARCH_sparc("__iob+"++show (``FILE_SIZE''::Int)
109 cvtLitLit "stderr" = IF_ARCH_alpha("_iob+"++show (2*(``FILE_SIZE''::Int))
110 ,IF_ARCH_i386("_IO_stderr_"
111 ,IF_ARCH_sparc("__iob+"++show (2*(``FILE_SIZE''::Int))
114 cvtLitLit "stdout" = IF_ARCH_alpha("_iob+56"{-dodgy *at best*...-}
115 ,IF_ARCH_i386("_IO_stdout_"
116 ,IF_ARCH_sparc("__iob+0x10"{-dodgy *at best*...-}
118 cvtLitLit "stderr" = IF_ARCH_alpha("_iob+112"{-dodgy *at best*...-}
119 ,IF_ARCH_i386("_IO_stderr_"
120 ,IF_ARCH_sparc("__iob+0x20"{-dodgy *at best*...-}
125 | otherwise = error ("Native code generator can't handle ``" ++ s ++ "''")
127 isHex ('0':'x':xs) = all isHexDigit xs
129 -- Now, where have I seen this before?
130 isHexDigit c = isDigit c || c >= 'A' && c <= 'F' || c >= 'a' && c <= 'f'
133 % ----------------------------------------------------------------
135 We (allegedly) put the first six C-call arguments in registers;
136 where do we start putting the rest of them?
138 eXTRA_STK_ARGS_HERE :: Int
140 = IF_ARCH_alpha(0, IF_ARCH_i386(23{-6x4bytes-}, IF_ARCH_sparc(23,???)))
143 % ----------------------------------------------------------------
145 @fixedHdrSizeInWords@ and @varHdrSizeInWords@: these are not dependent
146 on target architecture.
148 fixedHdrSizeInWords :: Int
151 = 1{-info ptr-} + profFHS + parFHS + tickyFHS
152 -- obviously, we aren't taking non-sequential too seriously yet
154 profFHS = if opt_SccProfilingOn then 1 else 0
155 parFHS = {-if PAR or GRAN then 1 else-} 0
156 tickyFHS = {-if ticky ... then 1 else-} 0
158 varHdrSizeInWords :: SMRep -> Int{-in words-}
163 SpecialisedRep _ _ _ _ -> 0
164 GenericRep _ _ _ -> 0
166 MuTupleRep _ -> 2 {- (1 + GC_MUT_RESERVED_WORDS) -}
170 PhantomRep -> panic "MachMisc.varHdrSizeInWords:phantom"
173 % - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
175 Static closure sizes:
177 charLikeSize, intLikeSize :: Int
179 charLikeSize = blahLikeSize CharLikeRep
180 intLikeSize = blahLikeSize IntLikeRep
183 = fromInteger (sizeOf PtrRep)
184 * (fixedHdrSizeInWords + varHdrSizeInWords blahLikeRep + 1)
186 blahLikeRep = SpecialisedRep blah 0 1 SMNormalForm
189 mutHS, dataHS :: StixTree
191 mutHS = blah_hs (MuTupleRep 0)
192 dataHS = blah_hs (DataRep 0)
195 = StInt (toInteger words)
197 words = fixedHdrSizeInWords + varHdrSizeInWords blah
200 % - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
202 Size of a @PrimRep@, in bytes.
205 sizeOf :: PrimRep -> Integer{-in bytes-}
206 -- the result is an Integer only because it's more convenient
208 sizeOf pr = case (primRepToSize pr) of
209 IF_ARCH_alpha({B -> 1; BU -> 1; {-W -> 2; WU -> 2; L -> 4; SF -> 4;-} _ -> 8},)
210 IF_ARCH_sparc({B -> 1; BU -> 1; {-HW -> 2; HWU -> 2;-} W -> 4; {-D -> 8;-} F -> 4; DF -> 8},)
211 IF_ARCH_i386( {B -> 1; {-S -> 2;-} L -> 4; F -> 4; DF -> 8 },)
214 % - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
216 Now the volatile saves and restores. We add the basic guys to the
217 list of ``user'' registers provided. Note that there are more basic
218 registers on the restore list, because some are reloaded from
221 (@volatileRestores@ used only for wrapper-hungry PrimOps.)
224 volatileSaves, volatileRestores :: [MagicId] -> [StixTree]
226 save_cands = [BaseReg,SpA,SuA,SpB,SuB,Hp,HpLim,RetReg]
227 restore_cands = save_cands ++ [StkStubReg,StdUpdRetVecReg]
230 = map save ((filter callerSaves) (save_cands ++ vols))
232 save x = StAssign (magicIdPrimRep x) loc reg
234 reg = StReg (StixMagicId x)
235 loc = case stgReg x of
237 Always _ -> panic "volatileSaves"
239 volatileRestores vols
240 = map restore ((filter callerSaves) (restore_cands ++ vols))
242 restore x = StAssign (magicIdPrimRep x) reg loc
244 reg = StReg (StixMagicId x)
245 loc = case stgReg x of
247 Always _ -> panic "volatileRestores"
250 % - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
252 Obviously slightly weedy
253 (Note that the floating point values aren't terribly important.)
256 targetMinDouble = MachDouble (-1.7976931348623157e+308)
257 targetMaxDouble = MachDouble (1.7976931348623157e+308)
258 targetMinInt = mkMachInt (-2147483647)
259 targetMaxInt = mkMachInt 2147483647
262 % - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
264 Storage manager nonsense. Note that the indices are dependent on
265 the definition of the smInfo structure in SMinterface.lh
268 storageMgrInfo, smCAFlist, smOldMutables, smOldLim :: StixTree
270 storageMgrInfo = sStLitLbl SLIT("StorageMgrInfo")
271 smCAFlist = StInd PtrRep (StIndex PtrRep storageMgrInfo (StInt SM_CAFLIST))
272 smOldMutables = StInd PtrRep (StIndex PtrRep storageMgrInfo (StInt SM_OLDMUTABLES))
273 smOldLim = StInd PtrRep (StIndex PtrRep storageMgrInfo (StInt SM_OLDLIM))
274 smStablePtrTable = StInd PtrRep (StIndex PtrRep storageMgrInfo (StInt SM_STABLEPOINTERTABLE))
277 % - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
279 This algorithm for determining the $\log_2$ of exact powers of 2 comes
280 from GCC. It requires bit manipulation primitives, and we use GHC
288 exactLog2 :: Integer -> Maybe Integer
290 = if (x <= 0 || x >= 2147483648) then
293 case (fromInteger x) of { I# x# ->
294 if (w2i ((i2w x#) `and#` (i2w (0# -# x#))) /=# x#) then
297 Just (toInteger (I# (pow2 x#)))
300 shiftr x y = shiftRA# x y
302 pow2 x# | x# ==# 1# = 0#
303 | otherwise = 1# +# pow2 (w2i (i2w x# `shiftr` i2w_s 1#))
306 % - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
310 #if alpha_TARGET_ARCH
311 = ALWAYS -- For BI (same as BR)
312 | EQQ -- For CMP and BI (NB: "EQ" is a 1.3 Prelude name)
314 | GTT -- For BI only (NB: "GT" is a 1.3 Prelude name)
315 | LE -- For CMP and BI
316 | LTT -- For CMP and BI (NB: "LT" is a 1.3 Prelude name)
318 | NEVER -- For BI (null instruction)
319 | ULE -- For CMP only
320 | ULT -- For CMP only
323 = ALWAYS -- What's really used? ToDo
337 #if sparc_TARGET_ARCH
338 = ALWAYS -- What's really used? ToDo
359 #if alpha_TARGET_ARCH
362 -- | W -- word (2 bytes): UNUSED
364 -- | L -- longword (4 bytes): UNUSED
365 | Q -- quadword (8 bytes)
366 -- | FF -- VAX F-style floating pt: UNUSED
367 -- | GF -- VAX G-style floating pt: UNUSED
368 -- | DF -- VAX D-style floating pt: UNUSED
369 -- | SF -- IEEE single-precision floating pt: UNUSED
370 | TF -- IEEE double-precision floating pt
374 -- | HB -- higher byte **UNUSED**
377 | F -- IEEE single-precision floating pt
378 | DF -- IEEE single-precision floating pt
380 #if sparc_TARGET_ARCH
382 | BU -- byte (unsigned)
383 -- | HW -- halfword, 2 bytes (signed): UNUSED
384 -- | HWU -- halfword, 2 bytes (unsigned): UNUSED
386 -- | D -- doubleword, 8 bytes: UNUSED
387 | F -- IEEE single-precision floating pt
388 | DF -- IEEE single-precision floating pt
391 primRepToSize :: PrimRep -> Size
393 primRepToSize PtrRep = IF_ARCH_alpha( Q, IF_ARCH_i386( L, IF_ARCH_sparc( W ,)))
394 primRepToSize CodePtrRep = IF_ARCH_alpha( Q, IF_ARCH_i386( L, IF_ARCH_sparc( W ,)))
395 primRepToSize DataPtrRep = IF_ARCH_alpha( Q, IF_ARCH_i386( L, IF_ARCH_sparc( W ,)))
396 primRepToSize RetRep = IF_ARCH_alpha( Q, IF_ARCH_i386( L, IF_ARCH_sparc( W ,)))
397 primRepToSize CostCentreRep = IF_ARCH_alpha( Q, IF_ARCH_i386( L, IF_ARCH_sparc( W ,)))
398 primRepToSize CharRep = IF_ARCH_alpha( BU, IF_ARCH_i386( L, IF_ARCH_sparc( BU,)))
399 primRepToSize IntRep = IF_ARCH_alpha( Q, IF_ARCH_i386( L, IF_ARCH_sparc( W ,)))
400 primRepToSize WordRep = IF_ARCH_alpha( Q, IF_ARCH_i386( L, IF_ARCH_sparc( W ,)))
401 primRepToSize AddrRep = IF_ARCH_alpha( Q, IF_ARCH_i386( L, IF_ARCH_sparc( W ,)))
402 primRepToSize FloatRep = IF_ARCH_alpha( TF, IF_ARCH_i386( F, IF_ARCH_sparc( F ,)))
403 primRepToSize DoubleRep = IF_ARCH_alpha( TF, IF_ARCH_i386( DF,IF_ARCH_sparc( DF,)))
404 primRepToSize ArrayRep = IF_ARCH_alpha( Q, IF_ARCH_i386( L, IF_ARCH_sparc( W ,)))
405 primRepToSize ByteArrayRep = IF_ARCH_alpha( Q, IF_ARCH_i386( L, IF_ARCH_sparc( W ,)))
406 primRepToSize StablePtrRep = IF_ARCH_alpha( Q, IF_ARCH_i386( L, IF_ARCH_sparc( W ,)))
407 primRepToSize ForeignObjRep = IF_ARCH_alpha( Q, IF_ARCH_i386( L, IF_ARCH_sparc( W ,)))
410 %************************************************************************
412 \subsection{Machine's assembly language}
414 %************************************************************************
416 We have a few common ``instructions'' (nearly all the pseudo-ops) but
417 mostly all of @Instr@ is machine-specific.
421 = COMMENT FAST_STRING -- comment pseudo-op
422 | SEGMENT CodeSegment -- {data,text} segment pseudo-op
423 | LABEL CLabel -- global label pseudo-op
424 | ASCII Bool -- True <=> needs backslash conversion
425 String -- the literal string
431 #if alpha_TARGET_ARCH
433 -- data Instr continues...
437 | LD Size Reg Addr -- size, dst, src
438 | LDA Reg Addr -- dst, src
439 | LDAH Reg Addr -- dst, src
440 | LDGP Reg Addr -- dst, src
441 | LDI Size Reg Imm -- size, dst, src
442 | ST Size Reg Addr -- size, src, dst
447 | ABS Size RI Reg -- size, src, dst
448 | NEG Size Bool RI Reg -- size, overflow, src, dst
449 | ADD Size Bool Reg RI Reg -- size, overflow, src, src, dst
450 | SADD Size Size Reg RI Reg -- size, scale, src, src, dst
451 | SUB Size Bool Reg RI Reg -- size, overflow, src, src, dst
452 | SSUB Size Size Reg RI Reg -- size, scale, src, src, dst
453 | MUL Size Bool Reg RI Reg -- size, overflow, src, src, dst
454 | DIV Size Bool Reg RI Reg -- size, unsigned, src, src, dst
455 | REM Size Bool Reg RI Reg -- size, unsigned, src, src, dst
457 -- Simple bit-twiddling.
477 | CMP Cond Reg RI Reg
484 | FADD Size Reg Reg Reg
485 | FDIV Size Reg Reg Reg
486 | FMUL Size Reg Reg Reg
487 | FSUB Size Reg Reg Reg
488 | CVTxy Size Size Reg Reg
489 | FCMP Size Cond Reg Reg Reg
501 -- Alpha-specific pseudo-ops.
510 #endif {- alpha_TARGET_ARCH -}
516 -- data Instr continues...
520 | MOV Size Operand Operand
521 | MOVZX Size Operand Operand -- size is the size of operand 2
522 | MOVSX Size Operand Operand -- size is the size of operand 2
524 -- Load effective address (also a very useful three-operand add instruction :-)
526 | LEA Size Operand Operand
530 | ADD Size Operand Operand
531 | SUB Size Operand Operand
533 -- Multiplication (signed and unsigned), Division (signed and unsigned),
534 -- result in %eax, %edx.
536 | IMUL Size Operand Operand
539 -- Simple bit-twiddling.
541 | AND Size Operand Operand
542 | OR Size Operand Operand
543 | XOR Size Operand Operand
545 | NEGI Size Operand -- NEG instruction (name clash with Cond)
546 | SHL Size Operand Operand -- 1st operand must be an Imm
547 | SAR Size Operand Operand -- 1st operand must be an Imm
548 | SHR Size Operand Operand -- 1st operand must be an Imm
551 -- Float Arithmetic. -- ToDo for 386
553 -- Note that we cheat by treating F{ABS,MOV,NEG} of doubles as single instructions
554 -- right up until we spit them out.
556 | SAHF -- stores ah into flags
558 | FADD Size Operand -- src
560 | FIADD Size Addr -- src
562 | FCOM Size Operand -- src
564 | FDIV Size Operand -- src
566 | FIDIV Size Addr -- src
567 | FDIVR Size Operand -- src
569 | FIDIVR Size Addr -- src
570 | FICOM Size Addr -- src
571 | FILD Size Addr Reg -- src, dst
572 | FIST Size Addr -- dst
573 | FLD Size Operand -- src
576 | FMUL Size Operand -- src
578 | FIMUL Size Addr -- src
582 | FST Size Operand -- dst
583 | FSTP Size Operand -- dst
584 | FSUB Size Operand -- src
586 | FISUB Size Addr -- src
587 | FSUBR Size Operand -- src
589 | FISUBR Size Addr -- src
591 | FCOMP Size Operand -- src
599 | TEST Size Operand Operand
600 | CMP Size Operand Operand
610 | JMP Operand -- target
611 | JXX Cond CLabel -- target
616 | CLTD -- sign extend %eax into %edx:%eax
619 = OpReg Reg -- register
620 | OpImm Imm -- immediate value
621 | OpAddr Addr -- memory reference
623 #endif {- i386_TARGET_ARCH -}
627 #if sparc_TARGET_ARCH
629 -- data Instr continues...
633 | LD Size Addr Reg -- size, src, dst
634 | ST Size Reg Addr -- size, src, dst
638 | ADD Bool Bool Reg RI Reg -- x?, cc?, src1, src2, dst
639 | SUB Bool Bool Reg RI Reg -- x?, cc?, src1, src2, dst
641 -- Simple bit-twiddling.
643 | AND Bool Reg RI Reg -- cc?, src1, src2, dst
644 | ANDN Bool Reg RI Reg -- cc?, src1, src2, dst
645 | OR Bool Reg RI Reg -- cc?, src1, src2, dst
646 | ORN Bool Reg RI Reg -- cc?, src1, src2, dst
647 | XOR Bool Reg RI Reg -- cc?, src1, src2, dst
648 | XNOR Bool Reg RI Reg -- cc?, src1, src2, dst
649 | SLL Reg RI Reg -- src1, src2, dst
650 | SRL Reg RI Reg -- src1, src2, dst
651 | SRA Reg RI Reg -- src1, src2, dst
652 | SETHI Imm Reg -- src, dst
653 | NOP -- Really SETHI 0, %g0, but worth an alias
657 -- Note that we cheat by treating F{ABS,MOV,NEG} of doubles as single instructions
658 -- right up until we spit them out.
660 | FABS Size Reg Reg -- src dst
661 | FADD Size Reg Reg Reg -- src1, src2, dst
662 | FCMP Bool Size Reg Reg -- exception?, src1, src2, dst
663 | FDIV Size Reg Reg Reg -- src1, src2, dst
664 | FMOV Size Reg Reg -- src, dst
665 | FMUL Size Reg Reg Reg -- src1, src2, dst
666 | FNEG Size Reg Reg -- src, dst
667 | FSQRT Size Reg Reg -- src, dst
668 | FSUB Size Reg Reg Reg -- src1, src2, dst
669 | FxTOy Size Size Reg Reg -- src, dst
673 | BI Cond Bool Imm -- cond, annul?, target
674 | BF Cond Bool Imm -- cond, annul?, target
677 | CALL Imm Int Bool -- target, args, terminal
684 riZero (RIImm (ImmInt 0)) = True
685 riZero (RIImm (ImmInteger 0)) = True
686 riZero (RIReg (FixedReg ILIT(0))) = True
689 #endif {- sparc_TARGET_ARCH -}