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, foHS,
14 sizeOf, primRepToSize,
18 volatileSaves, volatileRestores,
20 storageMgrInfo, smCAFlist, smOldLim, smOldMutables,
23 targetMaxDouble, targetMaxInt, targetMinDouble, targetMinInt,
30 Instr(..), IF_ARCH_i386(Operand(..) COMMA,)
44 IMPORT_1_3(Char(isDigit))
47 #if defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ <= 201
48 IMPORT_DELOOPER(AbsCLoop) ( fixedHdrSizeInWords, varHdrSizeInWords ) -- paranoia
49 IMPORT_DELOOPER(NcgLoop) ( underscorePrefix, fmtAsmLbl ) -- paranoia
52 import AbsCSyn ( MagicId(..) )
53 import AbsCUtils ( magicIdPrimRep )
54 import CLabel ( CLabel )
55 import CmdLineOpts ( opt_SccProfilingOn )
56 import Literal ( mkMachInt, Literal(..) )
57 import MachRegs ( stgReg, callerSaves, RegLoc(..),
59 #if __GLASGOW_HASKELL__ >= 202
61 import qualified MachRegs (Addr)
62 #define MachRegsAddr MachRegs.Addr
66 #define MachRegsAddr Addr
69 import OrdList ( OrdList )
70 import PrimRep ( PrimRep(..) )
71 import SMRep ( SMRep(..), SMSpecRepKind(..), SMUpdateKind(..) )
72 import Stix ( StixTree(..), StixReg(..), sStLitLbl,
79 underscorePrefix :: Bool -- leading underscore on labels?
83 ,{-else-} IF_ARCH_i386(
88 , {-otherwise-} False)))
90 ,{-else-}IF_ARCH_sparc(
91 IF_OS_sunos4(True, {-otherwise-} False)
94 ---------------------------
95 fmtAsmLbl :: String -> String -- for formatting labels
99 {- The alpha assembler likes temporary labels to look like $L123
100 instead of L123. (Don't toss the L, because then Lf28
108 ---------------------------
109 cvtLitLit :: String -> String
112 -- Rather than relying on guessing, use FILE_SIZE to compute the
115 cvtLitLit "stdin" = IF_ARCH_alpha("_iob+0" {-probably OK...-}
116 ,IF_ARCH_i386("_IO_stdin_"
117 ,IF_ARCH_sparc("__iob+0x0"{-probably OK...-}
120 cvtLitLit "stdout" = IF_ARCH_alpha("_iob+"++show (``FILE_SIZE''::Int)
121 ,IF_ARCH_i386("_IO_stdout_"
122 ,IF_ARCH_sparc("__iob+"++show (``FILE_SIZE''::Int)
124 cvtLitLit "stderr" = IF_ARCH_alpha("_iob+"++show (2*(``FILE_SIZE''::Int))
125 ,IF_ARCH_i386("_IO_stderr_"
126 ,IF_ARCH_sparc("__iob+"++show (2*(``FILE_SIZE''::Int))
129 cvtLitLit "stdout" = IF_ARCH_alpha("_iob+56"{-dodgy *at best*...-}
130 ,IF_ARCH_i386("_IO_stdout_"
131 ,IF_ARCH_sparc("__iob+0x10"{-dodgy *at best*...-}
133 cvtLitLit "stderr" = IF_ARCH_alpha("_iob+112"{-dodgy *at best*...-}
134 ,IF_ARCH_i386("_IO_stderr_"
135 ,IF_ARCH_sparc("__iob+0x20"{-dodgy *at best*...-}
140 | otherwise = error ("Native code generator can't handle ``" ++ s ++ "''")
142 isHex ('0':'x':xs) = all isHexDigit xs
144 -- Now, where have I seen this before?
145 isHexDigit c = isDigit c || c >= 'A' && c <= 'F' || c >= 'a' && c <= 'f'
148 % ----------------------------------------------------------------
150 We (allegedly) put the first six C-call arguments in registers;
151 where do we start putting the rest of them?
153 eXTRA_STK_ARGS_HERE :: Int
155 = IF_ARCH_alpha(0, IF_ARCH_i386(23{-6x4bytes-}, IF_ARCH_sparc(23,???)))
158 % ----------------------------------------------------------------
160 @fixedHdrSizeInWords@ and @varHdrSizeInWords@: these are not dependent
161 on target architecture.
163 fixedHdrSizeInWords :: Int
166 = 1{-info ptr-} + profFHS + parFHS + tickyFHS
167 -- obviously, we aren't taking non-sequential too seriously yet
169 profFHS = if opt_SccProfilingOn then 1 else 0
170 parFHS = {-if PAR or GRAN then 1 else-} 0
171 tickyFHS = {-if ticky ... then 1 else-} 0
173 varHdrSizeInWords :: SMRep -> Int{-in words-}
178 SpecialisedRep _ _ _ _ -> 0
179 GenericRep _ _ _ -> 0
181 MuTupleRep _ -> 2 {- (1 + GC_MUT_RESERVED_WORDS) -}
185 PhantomRep -> panic "MachMisc.varHdrSizeInWords:phantom"
188 % - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
190 Static closure sizes:
192 charLikeSize, intLikeSize :: Int
194 charLikeSize = blahLikeSize CharLikeRep
195 intLikeSize = blahLikeSize IntLikeRep
198 = fromInteger (sizeOf PtrRep)
199 * (fixedHdrSizeInWords + varHdrSizeInWords blahLikeRep + 1)
201 blahLikeRep = SpecialisedRep blah 0 1 SMNormalForm
204 mutHS, dataHS, foHS :: StixTree
206 mutHS = blah_hs (MuTupleRep 0)
207 dataHS = blah_hs (DataRep 0)
209 {- Semi-hack: to avoid introducing ForeignObjRep,
210 we hard-code the VHS for ForeignObj here.
213 = StInt (toInteger words)
215 words = fixedHdrSizeInWords + 1{-FOREIGN_VHS-}
218 = StInt (toInteger words)
220 words = fixedHdrSizeInWords + varHdrSizeInWords blah
223 % - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
225 Size of a @PrimRep@, in bytes.
228 sizeOf :: PrimRep -> Integer{-in bytes-}
229 -- the result is an Integer only because it's more convenient
231 sizeOf pr = case (primRepToSize pr) of
232 IF_ARCH_alpha({B -> 1; BU -> 1; {-W -> 2; WU -> 2; L -> 4; SF -> 4;-} _ -> 8},)
233 IF_ARCH_sparc({B -> 1; BU -> 1; {-HW -> 2; HWU -> 2;-} W -> 4; {-D -> 8;-} F -> 4; DF -> 8},)
234 IF_ARCH_i386( {B -> 1; {-S -> 2;-} L -> 4; F -> 4; DF -> 8 },)
237 % - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
239 Now the volatile saves and restores. We add the basic guys to the
240 list of ``user'' registers provided. Note that there are more basic
241 registers on the restore list, because some are reloaded from
244 (@volatileRestores@ used only for wrapper-hungry PrimOps.)
247 volatileSaves, volatileRestores :: [MagicId] -> [StixTree]
249 save_cands = [BaseReg,SpA,SuA,SpB,SuB,Hp,HpLim,RetReg]
250 restore_cands = save_cands ++ [StkStubReg,StdUpdRetVecReg]
253 = map save ((filter callerSaves) (save_cands ++ vols))
255 save x = StAssign (magicIdPrimRep x) loc reg
257 reg = StReg (StixMagicId x)
258 loc = case stgReg x of
260 Always _ -> panic "volatileSaves"
262 volatileRestores vols
263 = map restore ((filter callerSaves) (restore_cands ++ vols))
265 restore x = StAssign (magicIdPrimRep x) reg loc
267 reg = StReg (StixMagicId x)
268 loc = case stgReg x of
270 Always _ -> panic "volatileRestores"
273 % - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
275 Obviously slightly weedy
276 (Note that the floating point values aren't terribly important.)
279 targetMinDouble = MachDouble (-1.7976931348623157e+308)
280 targetMaxDouble = MachDouble (1.7976931348623157e+308)
281 targetMinInt = mkMachInt (-2147483647)
282 targetMaxInt = mkMachInt 2147483647
285 % - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
287 Storage manager nonsense. Note that the indices are dependent on
288 the definition of the smInfo structure in SMinterface.lh
291 storageMgrInfo, smCAFlist, smOldMutables, smOldLim :: StixTree
293 storageMgrInfo = sStLitLbl SLIT("StorageMgrInfo")
294 smCAFlist = StInd PtrRep (StIndex PtrRep storageMgrInfo (StInt SM_CAFLIST))
295 smOldMutables = StInd PtrRep (StIndex PtrRep storageMgrInfo (StInt SM_OLDMUTABLES))
296 smOldLim = StInd PtrRep (StIndex PtrRep storageMgrInfo (StInt SM_OLDLIM))
297 smStablePtrTable = StInd PtrRep (StIndex PtrRep storageMgrInfo (StInt SM_STABLEPOINTERTABLE))
300 % - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
302 This algorithm for determining the $\log_2$ of exact powers of 2 comes
303 from GCC. It requires bit manipulation primitives, and we use GHC
311 exactLog2 :: Integer -> Maybe Integer
313 = if (x <= 0 || x >= 2147483648) then
316 case (fromInteger x) of { I# x# ->
317 if (w2i ((i2w x#) `and#` (i2w (0# -# x#))) /=# x#) then
320 Just (toInteger (I# (pow2 x#)))
323 shiftr x y = shiftRA# x y
325 pow2 x# | x# ==# 1# = 0#
326 | otherwise = 1# +# pow2 (w2i (i2w x# `shiftr` i2w_s 1#))
329 % - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
333 #if alpha_TARGET_ARCH
334 = ALWAYS -- For BI (same as BR)
335 | EQQ -- For CMP and BI (NB: "EQ" is a 1.3 Prelude name)
337 | GTT -- For BI only (NB: "GT" is a 1.3 Prelude name)
338 | LE -- For CMP and BI
339 | LTT -- For CMP and BI (NB: "LT" is a 1.3 Prelude name)
341 | NEVER -- For BI (null instruction)
342 | ULE -- For CMP only
343 | ULT -- For CMP only
346 = ALWAYS -- What's really used? ToDo
360 #if sparc_TARGET_ARCH
361 = ALWAYS -- What's really used? ToDo
382 #if alpha_TARGET_ARCH
385 -- | W -- word (2 bytes): UNUSED
387 -- | L -- longword (4 bytes): UNUSED
388 | Q -- quadword (8 bytes)
389 -- | FF -- VAX F-style floating pt: UNUSED
390 -- | GF -- VAX G-style floating pt: UNUSED
391 -- | DF -- VAX D-style floating pt: UNUSED
392 -- | SF -- IEEE single-precision floating pt: UNUSED
393 | TF -- IEEE double-precision floating pt
397 -- | HB -- higher byte **UNUSED**
400 | F -- IEEE single-precision floating pt
401 | DF -- IEEE single-precision floating pt
403 #if sparc_TARGET_ARCH
405 | BU -- byte (unsigned)
406 -- | HW -- halfword, 2 bytes (signed): UNUSED
407 -- | HWU -- halfword, 2 bytes (unsigned): UNUSED
409 -- | D -- doubleword, 8 bytes: UNUSED
410 | F -- IEEE single-precision floating pt
411 | DF -- IEEE single-precision floating pt
414 primRepToSize :: PrimRep -> Size
416 primRepToSize PtrRep = IF_ARCH_alpha( Q, IF_ARCH_i386( L, IF_ARCH_sparc( W ,)))
417 primRepToSize CodePtrRep = IF_ARCH_alpha( Q, IF_ARCH_i386( L, IF_ARCH_sparc( W ,)))
418 primRepToSize DataPtrRep = IF_ARCH_alpha( Q, IF_ARCH_i386( L, IF_ARCH_sparc( W ,)))
419 primRepToSize RetRep = IF_ARCH_alpha( Q, IF_ARCH_i386( L, IF_ARCH_sparc( W ,)))
420 primRepToSize CostCentreRep = IF_ARCH_alpha( Q, IF_ARCH_i386( L, IF_ARCH_sparc( W ,)))
421 primRepToSize CharRep = IF_ARCH_alpha( BU, IF_ARCH_i386( L, IF_ARCH_sparc( BU,)))
422 primRepToSize IntRep = IF_ARCH_alpha( Q, IF_ARCH_i386( L, IF_ARCH_sparc( W ,)))
423 primRepToSize WordRep = IF_ARCH_alpha( Q, IF_ARCH_i386( L, IF_ARCH_sparc( W ,)))
424 primRepToSize AddrRep = IF_ARCH_alpha( Q, IF_ARCH_i386( L, IF_ARCH_sparc( W ,)))
425 primRepToSize FloatRep = IF_ARCH_alpha( TF, IF_ARCH_i386( F, IF_ARCH_sparc( F ,)))
426 primRepToSize DoubleRep = IF_ARCH_alpha( TF, IF_ARCH_i386( DF,IF_ARCH_sparc( DF,)))
427 primRepToSize ArrayRep = IF_ARCH_alpha( Q, IF_ARCH_i386( L, IF_ARCH_sparc( W ,)))
428 primRepToSize ByteArrayRep = IF_ARCH_alpha( Q, IF_ARCH_i386( L, IF_ARCH_sparc( W ,)))
429 primRepToSize StablePtrRep = IF_ARCH_alpha( Q, IF_ARCH_i386( L, IF_ARCH_sparc( W ,)))
430 primRepToSize ForeignObjRep = IF_ARCH_alpha( Q, IF_ARCH_i386( L, IF_ARCH_sparc( W ,)))
433 %************************************************************************
435 \subsection{Machine's assembly language}
437 %************************************************************************
439 We have a few common ``instructions'' (nearly all the pseudo-ops) but
440 mostly all of @Instr@ is machine-specific.
444 = COMMENT FAST_STRING -- comment pseudo-op
445 | SEGMENT CodeSegment -- {data,text} segment pseudo-op
446 | LABEL CLabel -- global label pseudo-op
447 | ASCII Bool -- True <=> needs backslash conversion
448 String -- the literal string
454 #if alpha_TARGET_ARCH
456 -- data Instr continues...
460 | LD Size Reg MachRegsAddr -- size, dst, src
461 | LDA Reg MachRegsAddr -- dst, src
462 | LDAH Reg MachRegsAddr -- dst, src
463 | LDGP Reg MachRegsAddr -- dst, src
464 | LDI Size Reg Imm -- size, dst, src
465 | ST Size Reg MachRegsAddr -- size, src, dst
470 | ABS Size RI Reg -- size, src, dst
471 | NEG Size Bool RI Reg -- size, overflow, src, dst
472 | ADD Size Bool Reg RI Reg -- size, overflow, src, src, dst
473 | SADD Size Size Reg RI Reg -- size, scale, src, src, dst
474 | SUB Size Bool Reg RI Reg -- size, overflow, src, src, dst
475 | SSUB Size Size Reg RI Reg -- size, scale, src, src, dst
476 | MUL Size Bool Reg RI Reg -- size, overflow, src, src, dst
477 | DIV Size Bool Reg RI Reg -- size, unsigned, src, src, dst
478 | REM Size Bool Reg RI Reg -- size, unsigned, src, src, dst
480 -- Simple bit-twiddling.
500 | CMP Cond Reg RI Reg
507 | FADD Size Reg Reg Reg
508 | FDIV Size Reg Reg Reg
509 | FMUL Size Reg Reg Reg
510 | FSUB Size Reg Reg Reg
511 | CVTxy Size Size Reg Reg
512 | FCMP Size Cond Reg Reg Reg
520 | JMP Reg MachRegsAddr Int
522 | JSR Reg MachRegsAddr Int
524 -- Alpha-specific pseudo-ops.
533 #endif {- alpha_TARGET_ARCH -}
539 -- data Instr continues...
543 | MOV Size Operand Operand
544 | MOVZX Size Operand Operand -- size is the size of operand 2
545 | MOVSX Size Operand Operand -- size is the size of operand 2
547 -- Load effective address (also a very useful three-operand add instruction :-)
549 | LEA Size Operand Operand
553 | ADD Size Operand Operand
554 | SUB Size Operand Operand
556 -- Multiplication (signed and unsigned), Division (signed and unsigned),
557 -- result in %eax, %edx.
559 | IMUL Size Operand Operand
562 -- Simple bit-twiddling.
564 | AND Size Operand Operand
565 | OR Size Operand Operand
566 | XOR Size Operand Operand
568 | NEGI Size Operand -- NEG instruction (name clash with Cond)
569 | SHL Size Operand Operand -- 1st operand must be an Imm
570 | SAR Size Operand Operand -- 1st operand must be an Imm
571 | SHR Size Operand Operand -- 1st operand must be an Imm
574 -- Float Arithmetic. -- ToDo for 386
576 -- Note that we cheat by treating F{ABS,MOV,NEG} of doubles as single instructions
577 -- right up until we spit them out.
579 | SAHF -- stores ah into flags
581 | FADD Size Operand -- src
583 | FIADD Size MachRegsAddr -- src
585 | FCOM Size Operand -- src
587 | FDIV Size Operand -- src
589 | FIDIV Size MachRegsAddr -- src
590 | FDIVR Size Operand -- src
592 | FIDIVR Size MachRegsAddr -- src
593 | FICOM Size MachRegsAddr -- src
594 | FILD Size MachRegsAddr Reg -- src, dst
595 | FIST Size MachRegsAddr -- dst
596 | FLD Size Operand -- src
599 | FMUL Size Operand -- src
601 | FIMUL Size MachRegsAddr -- src
605 | FST Size Operand -- dst
606 | FSTP Size Operand -- dst
607 | FSUB Size Operand -- src
609 | FISUB Size MachRegsAddr -- src
610 | FSUBR Size Operand -- src
612 | FISUBR Size MachRegsAddr -- src
614 | FCOMP Size Operand -- src
622 | TEST Size Operand Operand
623 | CMP Size Operand Operand
633 | JMP Operand -- target
634 | JXX Cond CLabel -- target
639 | CLTD -- sign extend %eax into %edx:%eax
642 = OpReg Reg -- register
643 | OpImm Imm -- immediate value
644 | OpAddr MachRegsAddr -- memory reference
646 #endif {- i386_TARGET_ARCH -}
650 #if sparc_TARGET_ARCH
652 -- data Instr continues...
656 | LD Size MachRegsAddr Reg -- size, src, dst
657 | ST Size Reg MachRegsAddr -- size, src, dst
661 | ADD Bool Bool Reg RI Reg -- x?, cc?, src1, src2, dst
662 | SUB Bool Bool Reg RI Reg -- x?, cc?, src1, src2, dst
664 -- Simple bit-twiddling.
666 | AND Bool Reg RI Reg -- cc?, src1, src2, dst
667 | ANDN Bool Reg RI Reg -- cc?, src1, src2, dst
668 | OR Bool Reg RI Reg -- cc?, src1, src2, dst
669 | ORN Bool Reg RI Reg -- cc?, src1, src2, dst
670 | XOR Bool Reg RI Reg -- cc?, src1, src2, dst
671 | XNOR Bool Reg RI Reg -- cc?, src1, src2, dst
672 | SLL Reg RI Reg -- src1, src2, dst
673 | SRL Reg RI Reg -- src1, src2, dst
674 | SRA Reg RI Reg -- src1, src2, dst
675 | SETHI Imm Reg -- src, dst
676 | NOP -- Really SETHI 0, %g0, but worth an alias
680 -- Note that we cheat by treating F{ABS,MOV,NEG} of doubles as single instructions
681 -- right up until we spit them out.
683 | FABS Size Reg Reg -- src dst
684 | FADD Size Reg Reg Reg -- src1, src2, dst
685 | FCMP Bool Size Reg Reg -- exception?, src1, src2, dst
686 | FDIV Size Reg Reg Reg -- src1, src2, dst
687 | FMOV Size Reg Reg -- src, dst
688 | FMUL Size Reg Reg Reg -- src1, src2, dst
689 | FNEG Size Reg Reg -- src, dst
690 | FSQRT Size Reg Reg -- src, dst
691 | FSUB Size Reg Reg Reg -- src1, src2, dst
692 | FxTOy Size Size Reg Reg -- src, dst
696 | BI Cond Bool Imm -- cond, annul?, target
697 | BF Cond Bool Imm -- cond, annul?, target
699 | JMP MachRegsAddr -- target
700 | CALL Imm Int Bool -- target, args, terminal
707 riZero (RIImm (ImmInt 0)) = True
708 riZero (RIImm (ImmInteger 0)) = True
709 riZero (RIReg (FixedReg ILIT(0))) = True
712 #endif {- sparc_TARGET_ARCH -}