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 CLabel ( CLabel )
52 import CmdLineOpts ( opt_SccProfilingOn )
53 import Literal ( mkMachInt, Literal(..) )
54 import MachRegs ( stgReg, callerSaves, RegLoc(..),
56 #if __GLASGOW_HASKELL__ >= 202
58 import qualified MachRegs (Addr)
59 #define MachRegsAddr MachRegs.Addr
63 #define MachRegsAddr Addr
66 import OrdList ( OrdList )
67 import PrimRep ( PrimRep(..) )
68 import SMRep ( SMRep(..), SMSpecRepKind(..), SMUpdateKind(..) )
69 import Stix ( StixTree(..), StixReg(..), sStLitLbl,
76 underscorePrefix :: Bool -- leading underscore on labels?
80 ,{-else-} IF_ARCH_i386(
85 , {-otherwise-} False)))
87 ,{-else-}IF_ARCH_sparc(
88 IF_OS_sunos4(True, {-otherwise-} False)
91 ---------------------------
92 fmtAsmLbl :: String -> String -- for formatting labels
96 {- The alpha assembler likes temporary labels to look like $L123
97 instead of L123. (Don't toss the L, because then Lf28
105 ---------------------------
106 cvtLitLit :: String -> String
109 -- Rather than relying on guessing, use FILE_SIZE to compute the
112 cvtLitLit "stdin" = IF_ARCH_alpha("_iob+0" {-probably OK...-}
113 ,IF_ARCH_i386("_IO_stdin_"
114 ,IF_ARCH_sparc("__iob+0x0"{-probably OK...-}
117 cvtLitLit "stdout" = IF_ARCH_alpha("_iob+"++show (``FILE_SIZE''::Int)
118 ,IF_ARCH_i386("_IO_stdout_"
119 ,IF_ARCH_sparc("__iob+"++show (``FILE_SIZE''::Int)
121 cvtLitLit "stderr" = IF_ARCH_alpha("_iob+"++show (2*(``FILE_SIZE''::Int))
122 ,IF_ARCH_i386("_IO_stderr_"
123 ,IF_ARCH_sparc("__iob+"++show (2*(``FILE_SIZE''::Int))
126 cvtLitLit "stdout" = IF_ARCH_alpha("_iob+56"{-dodgy *at best*...-}
127 ,IF_ARCH_i386("_IO_stdout_"
128 ,IF_ARCH_sparc("__iob+0x10"{-dodgy *at best*...-}
130 cvtLitLit "stderr" = IF_ARCH_alpha("_iob+112"{-dodgy *at best*...-}
131 ,IF_ARCH_i386("_IO_stderr_"
132 ,IF_ARCH_sparc("__iob+0x20"{-dodgy *at best*...-}
137 | otherwise = error ("Native code generator can't handle ``" ++ s ++ "''")
139 isHex ('0':'x':xs) = all isHexDigit xs
141 -- Now, where have I seen this before?
142 isHexDigit c = isDigit c || c >= 'A' && c <= 'F' || c >= 'a' && c <= 'f'
145 % ----------------------------------------------------------------
147 We (allegedly) put the first six C-call arguments in registers;
148 where do we start putting the rest of them?
150 eXTRA_STK_ARGS_HERE :: Int
152 = IF_ARCH_alpha(0, IF_ARCH_i386(23{-6x4bytes-}, IF_ARCH_sparc(23,???)))
155 % ----------------------------------------------------------------
157 @fixedHdrSizeInWords@ and @varHdrSizeInWords@: these are not dependent
158 on target architecture.
160 fixedHdrSizeInWords :: Int
163 = 1{-info ptr-} + profFHS + parFHS + tickyFHS
164 -- obviously, we aren't taking non-sequential too seriously yet
166 profFHS = if opt_SccProfilingOn then 1 else 0
167 parFHS = {-if PAR or GRAN then 1 else-} 0
168 tickyFHS = {-if ticky ... then 1 else-} 0
170 varHdrSizeInWords :: SMRep -> Int{-in words-}
175 SpecialisedRep _ _ _ _ -> 0
176 GenericRep _ _ _ -> 0
178 MuTupleRep _ -> 2 {- (1 + GC_MUT_RESERVED_WORDS) -}
182 PhantomRep -> panic "MachMisc.varHdrSizeInWords:phantom"
185 % - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
187 Static closure sizes:
189 charLikeSize, intLikeSize :: Int
191 charLikeSize = blahLikeSize CharLikeRep
192 intLikeSize = blahLikeSize IntLikeRep
195 = fromInteger (sizeOf PtrRep)
196 * (fixedHdrSizeInWords + varHdrSizeInWords blahLikeRep + 1)
198 blahLikeRep = SpecialisedRep blah 0 1 SMNormalForm
201 mutHS, dataHS :: StixTree
203 mutHS = blah_hs (MuTupleRep 0)
204 dataHS = blah_hs (DataRep 0)
207 = StInt (toInteger words)
209 words = fixedHdrSizeInWords + varHdrSizeInWords blah
212 % - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
214 Size of a @PrimRep@, in bytes.
217 sizeOf :: PrimRep -> Integer{-in bytes-}
218 -- the result is an Integer only because it's more convenient
220 sizeOf pr = case (primRepToSize pr) of
221 IF_ARCH_alpha({B -> 1; BU -> 1; {-W -> 2; WU -> 2; L -> 4; SF -> 4;-} _ -> 8},)
222 IF_ARCH_sparc({B -> 1; BU -> 1; {-HW -> 2; HWU -> 2;-} W -> 4; {-D -> 8;-} F -> 4; DF -> 8},)
223 IF_ARCH_i386( {B -> 1; {-S -> 2;-} L -> 4; F -> 4; DF -> 8 },)
226 % - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
228 Now the volatile saves and restores. We add the basic guys to the
229 list of ``user'' registers provided. Note that there are more basic
230 registers on the restore list, because some are reloaded from
233 (@volatileRestores@ used only for wrapper-hungry PrimOps.)
236 volatileSaves, volatileRestores :: [MagicId] -> [StixTree]
238 save_cands = [BaseReg,SpA,SuA,SpB,SuB,Hp,HpLim,RetReg]
239 restore_cands = save_cands ++ [StkStubReg,StdUpdRetVecReg]
242 = map save ((filter callerSaves) (save_cands ++ vols))
244 save x = StAssign (magicIdPrimRep x) loc reg
246 reg = StReg (StixMagicId x)
247 loc = case stgReg x of
249 Always _ -> panic "volatileSaves"
251 volatileRestores vols
252 = map restore ((filter callerSaves) (restore_cands ++ vols))
254 restore x = StAssign (magicIdPrimRep x) reg loc
256 reg = StReg (StixMagicId x)
257 loc = case stgReg x of
259 Always _ -> panic "volatileRestores"
262 % - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
264 Obviously slightly weedy
265 (Note that the floating point values aren't terribly important.)
268 targetMinDouble = MachDouble (-1.7976931348623157e+308)
269 targetMaxDouble = MachDouble (1.7976931348623157e+308)
270 targetMinInt = mkMachInt (-2147483647)
271 targetMaxInt = mkMachInt 2147483647
274 % - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
276 Storage manager nonsense. Note that the indices are dependent on
277 the definition of the smInfo structure in SMinterface.lh
280 storageMgrInfo, smCAFlist, smOldMutables, smOldLim :: StixTree
282 storageMgrInfo = sStLitLbl SLIT("StorageMgrInfo")
283 smCAFlist = StInd PtrRep (StIndex PtrRep storageMgrInfo (StInt SM_CAFLIST))
284 smOldMutables = StInd PtrRep (StIndex PtrRep storageMgrInfo (StInt SM_OLDMUTABLES))
285 smOldLim = StInd PtrRep (StIndex PtrRep storageMgrInfo (StInt SM_OLDLIM))
286 smStablePtrTable = StInd PtrRep (StIndex PtrRep storageMgrInfo (StInt SM_STABLEPOINTERTABLE))
289 % - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
291 This algorithm for determining the $\log_2$ of exact powers of 2 comes
292 from GCC. It requires bit manipulation primitives, and we use GHC
300 exactLog2 :: Integer -> Maybe Integer
302 = if (x <= 0 || x >= 2147483648) then
305 case (fromInteger x) of { I# x# ->
306 if (w2i ((i2w x#) `and#` (i2w (0# -# x#))) /=# x#) then
309 Just (toInteger (I# (pow2 x#)))
312 shiftr x y = shiftRA# x y
314 pow2 x# | x# ==# 1# = 0#
315 | otherwise = 1# +# pow2 (w2i (i2w x# `shiftr` i2w_s 1#))
318 % - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
322 #if alpha_TARGET_ARCH
323 = ALWAYS -- For BI (same as BR)
324 | EQQ -- For CMP and BI (NB: "EQ" is a 1.3 Prelude name)
326 | GTT -- For BI only (NB: "GT" is a 1.3 Prelude name)
327 | LE -- For CMP and BI
328 | LTT -- For CMP and BI (NB: "LT" is a 1.3 Prelude name)
330 | NEVER -- For BI (null instruction)
331 | ULE -- For CMP only
332 | ULT -- For CMP only
335 = ALWAYS -- What's really used? ToDo
349 #if sparc_TARGET_ARCH
350 = ALWAYS -- What's really used? ToDo
371 #if alpha_TARGET_ARCH
374 -- | W -- word (2 bytes): UNUSED
376 -- | L -- longword (4 bytes): UNUSED
377 | Q -- quadword (8 bytes)
378 -- | FF -- VAX F-style floating pt: UNUSED
379 -- | GF -- VAX G-style floating pt: UNUSED
380 -- | DF -- VAX D-style floating pt: UNUSED
381 -- | SF -- IEEE single-precision floating pt: UNUSED
382 | TF -- IEEE double-precision floating pt
386 -- | HB -- higher byte **UNUSED**
389 | F -- IEEE single-precision floating pt
390 | DF -- IEEE single-precision floating pt
392 #if sparc_TARGET_ARCH
394 | BU -- byte (unsigned)
395 -- | HW -- halfword, 2 bytes (signed): UNUSED
396 -- | HWU -- halfword, 2 bytes (unsigned): UNUSED
398 -- | D -- doubleword, 8 bytes: UNUSED
399 | F -- IEEE single-precision floating pt
400 | DF -- IEEE single-precision floating pt
403 primRepToSize :: PrimRep -> Size
405 primRepToSize PtrRep = IF_ARCH_alpha( Q, IF_ARCH_i386( L, IF_ARCH_sparc( W ,)))
406 primRepToSize CodePtrRep = IF_ARCH_alpha( Q, IF_ARCH_i386( L, IF_ARCH_sparc( W ,)))
407 primRepToSize DataPtrRep = IF_ARCH_alpha( Q, IF_ARCH_i386( L, IF_ARCH_sparc( W ,)))
408 primRepToSize RetRep = IF_ARCH_alpha( Q, IF_ARCH_i386( L, IF_ARCH_sparc( W ,)))
409 primRepToSize CostCentreRep = IF_ARCH_alpha( Q, IF_ARCH_i386( L, IF_ARCH_sparc( W ,)))
410 primRepToSize CharRep = IF_ARCH_alpha( BU, IF_ARCH_i386( L, IF_ARCH_sparc( BU,)))
411 primRepToSize IntRep = IF_ARCH_alpha( Q, IF_ARCH_i386( L, IF_ARCH_sparc( W ,)))
412 primRepToSize WordRep = IF_ARCH_alpha( Q, IF_ARCH_i386( L, IF_ARCH_sparc( W ,)))
413 primRepToSize AddrRep = IF_ARCH_alpha( Q, IF_ARCH_i386( L, IF_ARCH_sparc( W ,)))
414 primRepToSize FloatRep = IF_ARCH_alpha( TF, IF_ARCH_i386( F, IF_ARCH_sparc( F ,)))
415 primRepToSize DoubleRep = IF_ARCH_alpha( TF, IF_ARCH_i386( DF,IF_ARCH_sparc( DF,)))
416 primRepToSize ArrayRep = IF_ARCH_alpha( Q, IF_ARCH_i386( L, IF_ARCH_sparc( W ,)))
417 primRepToSize ByteArrayRep = IF_ARCH_alpha( Q, IF_ARCH_i386( L, IF_ARCH_sparc( W ,)))
418 primRepToSize StablePtrRep = IF_ARCH_alpha( Q, IF_ARCH_i386( L, IF_ARCH_sparc( W ,)))
419 primRepToSize ForeignObjRep = IF_ARCH_alpha( Q, IF_ARCH_i386( L, IF_ARCH_sparc( W ,)))
422 %************************************************************************
424 \subsection{Machine's assembly language}
426 %************************************************************************
428 We have a few common ``instructions'' (nearly all the pseudo-ops) but
429 mostly all of @Instr@ is machine-specific.
433 = COMMENT FAST_STRING -- comment pseudo-op
434 | SEGMENT CodeSegment -- {data,text} segment pseudo-op
435 | LABEL CLabel -- global label pseudo-op
436 | ASCII Bool -- True <=> needs backslash conversion
437 String -- the literal string
443 #if alpha_TARGET_ARCH
445 -- data Instr continues...
449 | LD Size Reg MachRegsAddr -- size, dst, src
450 | LDA Reg MachRegsAddr -- dst, src
451 | LDAH Reg MachRegsAddr -- dst, src
452 | LDGP Reg MachRegsAddr -- dst, src
453 | LDI Size Reg Imm -- size, dst, src
454 | ST Size Reg MachRegsAddr -- size, src, dst
459 | ABS Size RI Reg -- size, src, dst
460 | NEG Size Bool RI Reg -- size, overflow, src, dst
461 | ADD Size Bool Reg RI Reg -- size, overflow, src, src, dst
462 | SADD Size Size Reg RI Reg -- size, scale, src, src, dst
463 | SUB Size Bool Reg RI Reg -- size, overflow, src, src, dst
464 | SSUB Size Size Reg RI Reg -- size, scale, src, src, dst
465 | MUL Size Bool Reg RI Reg -- size, overflow, src, src, dst
466 | DIV Size Bool Reg RI Reg -- size, unsigned, src, src, dst
467 | REM Size Bool Reg RI Reg -- size, unsigned, src, src, dst
469 -- Simple bit-twiddling.
489 | CMP Cond Reg RI Reg
496 | FADD Size Reg Reg Reg
497 | FDIV Size Reg Reg Reg
498 | FMUL Size Reg Reg Reg
499 | FSUB Size Reg Reg Reg
500 | CVTxy Size Size Reg Reg
501 | FCMP Size Cond Reg Reg Reg
509 | JMP Reg MachRegsAddr Int
511 | JSR Reg MachRegsAddr Int
513 -- Alpha-specific pseudo-ops.
522 #endif {- alpha_TARGET_ARCH -}
528 -- data Instr continues...
532 | MOV Size Operand Operand
533 | MOVZX Size Operand Operand -- size is the size of operand 2
534 | MOVSX Size Operand Operand -- size is the size of operand 2
536 -- Load effective address (also a very useful three-operand add instruction :-)
538 | LEA Size Operand Operand
542 | ADD Size Operand Operand
543 | SUB Size Operand Operand
545 -- Multiplication (signed and unsigned), Division (signed and unsigned),
546 -- result in %eax, %edx.
548 | IMUL Size Operand Operand
551 -- Simple bit-twiddling.
553 | AND Size Operand Operand
554 | OR Size Operand Operand
555 | XOR Size Operand Operand
557 | NEGI Size Operand -- NEG instruction (name clash with Cond)
558 | SHL Size Operand Operand -- 1st operand must be an Imm
559 | SAR Size Operand Operand -- 1st operand must be an Imm
560 | SHR Size Operand Operand -- 1st operand must be an Imm
563 -- Float Arithmetic. -- ToDo for 386
565 -- Note that we cheat by treating F{ABS,MOV,NEG} of doubles as single instructions
566 -- right up until we spit them out.
568 | SAHF -- stores ah into flags
570 | FADD Size Operand -- src
572 | FIADD Size MachRegsAddr -- src
574 | FCOM Size Operand -- src
576 | FDIV Size Operand -- src
578 | FIDIV Size MachRegsAddr -- src
579 | FDIVR Size Operand -- src
581 | FIDIVR Size MachRegsAddr -- src
582 | FICOM Size MachRegsAddr -- src
583 | FILD Size MachRegsAddr Reg -- src, dst
584 | FIST Size MachRegsAddr -- dst
585 | FLD Size Operand -- src
588 | FMUL Size Operand -- src
590 | FIMUL Size MachRegsAddr -- src
594 | FST Size Operand -- dst
595 | FSTP Size Operand -- dst
596 | FSUB Size Operand -- src
598 | FISUB Size MachRegsAddr -- src
599 | FSUBR Size Operand -- src
601 | FISUBR Size MachRegsAddr -- src
603 | FCOMP Size Operand -- src
611 | TEST Size Operand Operand
612 | CMP Size Operand Operand
622 | JMP Operand -- target
623 | JXX Cond CLabel -- target
628 | CLTD -- sign extend %eax into %edx:%eax
631 = OpReg Reg -- register
632 | OpImm Imm -- immediate value
633 | OpAddr MachRegsAddr -- memory reference
635 #endif {- i386_TARGET_ARCH -}
639 #if sparc_TARGET_ARCH
641 -- data Instr continues...
645 | LD Size MachRegsAddr Reg -- size, src, dst
646 | ST Size Reg MachRegsAddr -- size, src, dst
650 | ADD Bool Bool Reg RI Reg -- x?, cc?, src1, src2, dst
651 | SUB Bool Bool Reg RI Reg -- x?, cc?, src1, src2, dst
653 -- Simple bit-twiddling.
655 | AND Bool Reg RI Reg -- cc?, src1, src2, dst
656 | ANDN Bool Reg RI Reg -- cc?, src1, src2, dst
657 | OR Bool Reg RI Reg -- cc?, src1, src2, dst
658 | ORN Bool Reg RI Reg -- cc?, src1, src2, dst
659 | XOR Bool Reg RI Reg -- cc?, src1, src2, dst
660 | XNOR Bool Reg RI Reg -- cc?, src1, src2, dst
661 | SLL Reg RI Reg -- src1, src2, dst
662 | SRL Reg RI Reg -- src1, src2, dst
663 | SRA Reg RI Reg -- src1, src2, dst
664 | SETHI Imm Reg -- src, dst
665 | NOP -- Really SETHI 0, %g0, but worth an alias
669 -- Note that we cheat by treating F{ABS,MOV,NEG} of doubles as single instructions
670 -- right up until we spit them out.
672 | FABS Size Reg Reg -- src dst
673 | FADD Size Reg Reg Reg -- src1, src2, dst
674 | FCMP Bool Size Reg Reg -- exception?, src1, src2, dst
675 | FDIV Size Reg Reg Reg -- src1, src2, dst
676 | FMOV Size Reg Reg -- src, dst
677 | FMUL Size Reg Reg Reg -- src1, src2, dst
678 | FNEG Size Reg Reg -- src, dst
679 | FSQRT Size Reg Reg -- src, dst
680 | FSUB Size Reg Reg Reg -- src1, src2, dst
681 | FxTOy Size Size Reg Reg -- src, dst
685 | BI Cond Bool Imm -- cond, annul?, target
686 | BF Cond Bool Imm -- cond, annul?, target
688 | JMP MachRegsAddr -- target
689 | CALL Imm Int Bool -- target, args, terminal
696 riZero (RIImm (ImmInt 0)) = True
697 riZero (RIImm (ImmInteger 0)) = True
698 riZero (RIReg (FixedReg ILIT(0))) = True
701 #endif {- sparc_TARGET_ARCH -}