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 AbsCLoop ( fixedHdrSizeInWords, varHdrSizeInWords ) -- paranoia
46 import NcgLoop ( underscorePrefix, fmtAsmLbl ) -- paranoia
48 import AbsCSyn ( MagicId(..) )
49 import AbsCUtils ( magicIdPrimRep )
50 import CmdLineOpts ( opt_SccProfilingOn )
51 import Literal ( mkMachInt, Literal(..) )
52 import MachRegs ( stgReg, callerSaves, RegLoc(..),
53 Imm(..), Reg(..), Addr
55 import OrdList ( OrdList )
56 import PrimRep ( PrimRep(..) )
57 import SMRep ( SMRep(..), SMSpecRepKind(..), SMUpdateKind(..) )
58 import Stix ( StixTree(..), StixReg(..), sStLitLbl,
65 underscorePrefix :: Bool -- leading underscore on labels?
69 ,{-else-} IF_ARCH_i386(
73 , {-otherwise-} False)))
74 ,{-else-}IF_ARCH_sparc(
75 IF_OS_sunos4(True, {-otherwise-} False)
78 ---------------------------
79 fmtAsmLbl :: String -> String -- for formatting labels
83 {- The alpha assembler likes temporary labels to look like $L123
84 instead of L123. (Don't toss the L, because then Lf28
92 ---------------------------
93 cvtLitLit :: String -> String
95 -- ToDo: some kind of *careful* attention needed...
97 cvtLitLit "stdin" = IF_ARCH_alpha("_iob+0" {-probably OK...-}
98 ,IF_ARCH_i386("_IO_stdin_"
99 ,IF_ARCH_sparc("__iob+0x0"{-probably OK...-}
101 cvtLitLit "stdout" = IF_ARCH_alpha("_iob+56"{-dodgy *at best*...-}
102 ,IF_ARCH_i386("_IO_stdout_"
103 ,IF_ARCH_sparc("__iob+0x14"{-dodgy *at best*...-}
105 cvtLitLit "stderr" = IF_ARCH_alpha("_iob+112"{-dodgy *at best*...-}
106 ,IF_ARCH_i386("_IO_stderr_"
107 ,IF_ARCH_sparc("__iob+0x28"{-dodgy *at best*...-}
111 | otherwise = error ("Native code generator can't handle ``" ++ s ++ "''")
113 isHex ('0':'x':xs) = all isHexDigit xs
115 -- Now, where have I seen this before?
116 isHexDigit c = isDigit c || c >= 'A' && c <= 'F' || c >= 'a' && c <= 'f'
119 % ----------------------------------------------------------------
121 We (allegedly) put the first six C-call arguments in registers;
122 where do we start putting the rest of them?
124 eXTRA_STK_ARGS_HERE :: Int
126 = IF_ARCH_alpha(0, IF_ARCH_i386(23{-6x4bytes-}, IF_ARCH_sparc(23,???)))
129 % ----------------------------------------------------------------
131 @fixedHdrSizeInWords@ and @varHdrSizeInWords@: these are not dependent
132 on target architecture.
134 fixedHdrSizeInWords :: Int
137 = 1{-info ptr-} + profFHS + parFHS + tickyFHS
138 -- obviously, we aren't taking non-sequential too seriously yet
140 profFHS = if opt_SccProfilingOn then 1 else 0
141 parFHS = {-if PAR or GRAN then 1 else-} 0
142 tickyFHS = {-if ticky ... then 1 else-} 0
144 varHdrSizeInWords :: SMRep -> Int{-in words-}
149 SpecialisedRep _ _ _ _ -> 0
150 GenericRep _ _ _ -> 0
152 MuTupleRep _ -> 2 {- (1 + GC_MUT_RESERVED_WORDS) -}
156 PhantomRep -> panic "MachMisc.varHdrSizeInWords:phantom"
159 % - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
161 Static closure sizes:
163 charLikeSize, intLikeSize :: Int
165 charLikeSize = blahLikeSize CharLikeRep
166 intLikeSize = blahLikeSize IntLikeRep
169 = fromInteger (sizeOf PtrRep)
170 * (fixedHdrSizeInWords + varHdrSizeInWords blahLikeRep + 1)
172 blahLikeRep = SpecialisedRep blah 0 1 SMNormalForm
175 mutHS, dataHS :: StixTree
177 mutHS = blah_hs (MuTupleRep 0)
178 dataHS = blah_hs (DataRep 0)
181 = StInt (toInteger words)
183 words = fixedHdrSizeInWords + varHdrSizeInWords blah
186 % - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
188 Size of a @PrimRep@, in bytes.
191 sizeOf :: PrimRep -> Integer{-in bytes-}
192 -- the result is an Integer only because it's more convenient
194 sizeOf pr = case (primRepToSize pr) of
195 IF_ARCH_alpha({B -> 1; BU -> 1; {-W -> 2; WU -> 2; L -> 4; SF -> 4;-} _ -> 8},)
196 IF_ARCH_sparc({B -> 1; BU -> 1; {-HW -> 2; HWU -> 2;-} W -> 4; {-D -> 8;-} F -> 4; DF -> 8},)
197 IF_ARCH_i386( {B -> 1; {-S -> 2;-} L -> 4; F -> 4; DF -> 8 },)
200 % - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
202 Now the volatile saves and restores. We add the basic guys to the
203 list of ``user'' registers provided. Note that there are more basic
204 registers on the restore list, because some are reloaded from
207 (@volatileRestores@ used only for wrapper-hungry PrimOps.)
210 volatileSaves, volatileRestores :: [MagicId] -> [StixTree]
212 save_cands = [BaseReg,SpA,SuA,SpB,SuB,Hp,HpLim,RetReg]
213 restore_cands = save_cands ++ [StkStubReg,StdUpdRetVecReg]
216 = map save ((filter callerSaves) (save_cands ++ vols))
218 save x = StAssign (magicIdPrimRep x) loc reg
220 reg = StReg (StixMagicId x)
221 loc = case stgReg x of
223 Always _ -> panic "volatileSaves"
225 volatileRestores vols
226 = map restore ((filter callerSaves) (restore_cands ++ vols))
228 restore x = StAssign (magicIdPrimRep x) reg loc
230 reg = StReg (StixMagicId x)
231 loc = case stgReg x of
233 Always _ -> panic "volatileRestores"
236 % - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
238 Obviously slightly weedy
239 (Note that the floating point values aren't terribly important.)
242 targetMinDouble = MachDouble (-1.7976931348623157e+308)
243 targetMaxDouble = MachDouble (1.7976931348623157e+308)
244 targetMinInt = mkMachInt (-2147483647)
245 targetMaxInt = mkMachInt 2147483647
248 % - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
250 Storage manager nonsense. Note that the indices are dependent on
251 the definition of the smInfo structure in SMinterface.lh
254 storageMgrInfo, smCAFlist, smOldMutables, smOldLim :: StixTree
256 storageMgrInfo = sStLitLbl SLIT("StorageMgrInfo")
257 smCAFlist = StInd PtrRep (StIndex PtrRep storageMgrInfo (StInt SM_CAFLIST))
258 smOldMutables = StInd PtrRep (StIndex PtrRep storageMgrInfo (StInt SM_OLDMUTABLES))
259 smOldLim = StInd PtrRep (StIndex PtrRep storageMgrInfo (StInt SM_OLDLIM))
260 smStablePtrTable = StInd PtrRep (StIndex PtrRep storageMgrInfo (StInt SM_STABLEPOINTERTABLE))
263 % - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
265 This algorithm for determining the $\log_2$ of exact powers of 2 comes
266 from GCC. It requires bit manipulation primitives, and we use GHC
274 exactLog2 :: Integer -> Maybe Integer
276 = if (x <= 0 || x >= 2147483648) then
279 case (fromInteger x) of { I# x# ->
280 if (w2i ((i2w x#) `and#` (i2w (0# -# x#))) /=# x#) then
283 Just (toInteger (I# (pow2 x#)))
286 shiftr x y = shiftRA# x y
288 pow2 x# | x# ==# 1# = 0#
289 | otherwise = 1# +# pow2 (w2i (i2w x# `shiftr` i2w_s 1#))
292 % - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
296 #if alpha_TARGET_ARCH
297 = ALWAYS -- For BI (same as BR)
298 | EQ -- For CMP and BI
301 | LE -- For CMP and BI
302 | LT -- For CMP and BI
304 | NEVER -- For BI (null instruction)
305 | ULE -- For CMP only
306 | ULT -- For CMP only
309 = ALWAYS -- What's really used? ToDo
323 #if sparc_TARGET_ARCH
324 = ALWAYS -- What's really used? ToDo
345 #if alpha_TARGET_ARCH
348 -- | W -- word (2 bytes): UNUSED
350 -- | L -- longword (4 bytes): UNUSED
351 | Q -- quadword (8 bytes)
352 -- | FF -- VAX F-style floating pt: UNUSED
353 -- | GF -- VAX G-style floating pt: UNUSED
354 -- | DF -- VAX D-style floating pt: UNUSED
355 -- | SF -- IEEE single-precision floating pt: UNUSED
356 | TF -- IEEE double-precision floating pt
360 -- | HB -- higher byte **UNUSED**
363 | F -- IEEE single-precision floating pt
364 | DF -- IEEE single-precision floating pt
366 #if sparc_TARGET_ARCH
368 | BU -- byte (unsigned)
369 -- | HW -- halfword, 2 bytes (signed): UNUSED
370 -- | HWU -- halfword, 2 bytes (unsigned): UNUSED
372 -- | D -- doubleword, 8 bytes: UNUSED
373 | F -- IEEE single-precision floating pt
374 | DF -- IEEE single-precision floating pt
377 primRepToSize :: PrimRep -> Size
379 primRepToSize PtrRep = IF_ARCH_alpha( Q, IF_ARCH_i386( L, IF_ARCH_sparc( W ,)))
380 primRepToSize CodePtrRep = IF_ARCH_alpha( Q, IF_ARCH_i386( L, IF_ARCH_sparc( W ,)))
381 primRepToSize DataPtrRep = IF_ARCH_alpha( Q, IF_ARCH_i386( L, IF_ARCH_sparc( W ,)))
382 primRepToSize RetRep = IF_ARCH_alpha( Q, IF_ARCH_i386( L, IF_ARCH_sparc( W ,)))
383 primRepToSize CostCentreRep = IF_ARCH_alpha( Q, IF_ARCH_i386( L, IF_ARCH_sparc( W ,)))
384 primRepToSize CharRep = IF_ARCH_alpha( BU, IF_ARCH_i386( L, IF_ARCH_sparc( BU,)))
385 primRepToSize IntRep = IF_ARCH_alpha( Q, IF_ARCH_i386( L, IF_ARCH_sparc( W ,)))
386 primRepToSize WordRep = IF_ARCH_alpha( Q, IF_ARCH_i386( L, IF_ARCH_sparc( W ,)))
387 primRepToSize AddrRep = IF_ARCH_alpha( Q, IF_ARCH_i386( L, IF_ARCH_sparc( W ,)))
388 primRepToSize FloatRep = IF_ARCH_alpha( TF, IF_ARCH_i386( F, IF_ARCH_sparc( F ,)))
389 primRepToSize DoubleRep = IF_ARCH_alpha( TF, IF_ARCH_i386( DF,IF_ARCH_sparc( DF,)))
390 primRepToSize ArrayRep = IF_ARCH_alpha( Q, IF_ARCH_i386( L, IF_ARCH_sparc( W ,)))
391 primRepToSize ByteArrayRep = IF_ARCH_alpha( Q, IF_ARCH_i386( L, IF_ARCH_sparc( W ,)))
392 primRepToSize StablePtrRep = IF_ARCH_alpha( Q, IF_ARCH_i386( L, IF_ARCH_sparc( W ,)))
393 primRepToSize MallocPtrRep = IF_ARCH_alpha( Q, IF_ARCH_i386( L, IF_ARCH_sparc( W ,)))
396 %************************************************************************
398 \subsection{Machine's assembly language}
400 %************************************************************************
402 We have a few common ``instructions'' (nearly all the pseudo-ops) but
403 mostly all of @Instr@ is machine-specific.
407 = COMMENT FAST_STRING -- comment pseudo-op
408 | SEGMENT CodeSegment -- {data,text} segment pseudo-op
409 | LABEL CLabel -- global label pseudo-op
410 | ASCII Bool -- True <=> needs backslash conversion
411 String -- the literal string
417 #if alpha_TARGET_ARCH
419 -- data Instr continues...
423 | LD Size Reg Addr -- size, dst, src
424 | LDA Reg Addr -- dst, src
425 | LDAH Reg Addr -- dst, src
426 | LDGP Reg Addr -- dst, src
427 | LDI Size Reg Imm -- size, dst, src
428 | ST Size Reg Addr -- size, src, dst
433 | ABS Size RI Reg -- size, src, dst
434 | NEG Size Bool RI Reg -- size, overflow, src, dst
435 | ADD Size Bool Reg RI Reg -- size, overflow, src, src, dst
436 | SADD Size Size Reg RI Reg -- size, scale, src, src, dst
437 | SUB Size Bool Reg RI Reg -- size, overflow, src, src, dst
438 | SSUB Size Size Reg RI Reg -- size, scale, src, src, dst
439 | MUL Size Bool Reg RI Reg -- size, overflow, src, src, dst
440 | DIV Size Bool Reg RI Reg -- size, unsigned, src, src, dst
441 | REM Size Bool Reg RI Reg -- size, unsigned, src, src, dst
443 -- Simple bit-twiddling.
463 | CMP Cond Reg RI Reg
470 | FADD Size Reg Reg Reg
471 | FDIV Size Reg Reg Reg
472 | FMUL Size Reg Reg Reg
473 | FSUB Size Reg Reg Reg
474 | CVTxy Size Size Reg Reg
475 | FCMP Size Cond Reg Reg Reg
487 -- Alpha-specific pseudo-ops.
496 #endif {- alpha_TARGET_ARCH -}
502 -- data Instr continues...
506 | MOV Size Operand Operand
507 | MOVZX Size Operand Operand -- size is the size of operand 2
508 | MOVSX Size Operand Operand -- size is the size of operand 2
510 -- Load effective address (also a very useful three-operand add instruction :-)
512 | LEA Size Operand Operand
516 | ADD Size Operand Operand
517 | SUB Size Operand Operand
519 -- Multiplication (signed and unsigned), Division (signed and unsigned),
520 -- result in %eax, %edx.
522 | IMUL Size Operand Operand
525 -- Simple bit-twiddling.
527 | AND Size Operand Operand
528 | OR Size Operand Operand
529 | XOR Size Operand Operand
531 | NEGI Size Operand -- NEG instruction (name clash with Cond)
532 | SHL Size Operand Operand -- 1st operand must be an Imm
533 | SAR Size Operand Operand -- 1st operand must be an Imm
534 | SHR Size Operand Operand -- 1st operand must be an Imm
537 -- Float Arithmetic. -- ToDo for 386
539 -- Note that we cheat by treating F{ABS,MOV,NEG} of doubles as single instructions
540 -- right up until we spit them out.
542 | SAHF -- stores ah into flags
544 | FADD Size Operand -- src
546 | FIADD Size Addr -- src
548 | FCOM Size Operand -- src
550 | FDIV Size Operand -- src
552 | FIDIV Size Addr -- src
553 | FDIVR Size Operand -- src
555 | FIDIVR Size Addr -- src
556 | FICOM Size Addr -- src
557 | FILD Size Addr Reg -- src, dst
558 | FIST Size Addr -- dst
559 | FLD Size Operand -- src
562 | FMUL Size Operand -- src
564 | FIMUL Size Addr -- src
568 | FST Size Operand -- dst
569 | FSTP Size Operand -- dst
570 | FSUB Size Operand -- src
572 | FISUB Size Addr -- src
573 | FSUBR Size Operand -- src
575 | FISUBR Size Addr -- src
577 | FCOMP Size Operand -- src
585 | TEST Size Operand Operand
586 | CMP Size Operand Operand
596 | JMP Operand -- target
597 | JXX Cond CLabel -- target
602 | CLTD -- sign extend %eax into %edx:%eax
605 = OpReg Reg -- register
606 | OpImm Imm -- immediate value
607 | OpAddr Addr -- memory reference
609 #endif {- i386_TARGET_ARCH -}
613 #if sparc_TARGET_ARCH
615 -- data Instr continues...
619 | LD Size Addr Reg -- size, src, dst
620 | ST Size Reg Addr -- size, src, dst
624 | ADD Bool Bool Reg RI Reg -- x?, cc?, src1, src2, dst
625 | SUB Bool Bool Reg RI Reg -- x?, cc?, src1, src2, dst
627 -- Simple bit-twiddling.
629 | AND Bool Reg RI Reg -- cc?, src1, src2, dst
630 | ANDN Bool Reg RI Reg -- cc?, src1, src2, dst
631 | OR Bool Reg RI Reg -- cc?, src1, src2, dst
632 | ORN Bool Reg RI Reg -- cc?, src1, src2, dst
633 | XOR Bool Reg RI Reg -- cc?, src1, src2, dst
634 | XNOR Bool Reg RI Reg -- cc?, src1, src2, dst
635 | SLL Reg RI Reg -- src1, src2, dst
636 | SRL Reg RI Reg -- src1, src2, dst
637 | SRA Reg RI Reg -- src1, src2, dst
638 | SETHI Imm Reg -- src, dst
639 | NOP -- Really SETHI 0, %g0, but worth an alias
643 -- Note that we cheat by treating F{ABS,MOV,NEG} of doubles as single instructions
644 -- right up until we spit them out.
646 | FABS Size Reg Reg -- src dst
647 | FADD Size Reg Reg Reg -- src1, src2, dst
648 | FCMP Bool Size Reg Reg -- exception?, src1, src2, dst
649 | FDIV Size Reg Reg Reg -- src1, src2, dst
650 | FMOV Size Reg Reg -- src, dst
651 | FMUL Size Reg Reg Reg -- src1, src2, dst
652 | FNEG Size Reg Reg -- src, dst
653 | FSQRT Size Reg Reg -- src, dst
654 | FSUB Size Reg Reg Reg -- src1, src2, dst
655 | FxTOy Size Size Reg Reg -- src, dst
659 | BI Cond Bool Imm -- cond, annul?, target
660 | BF Cond Bool Imm -- cond, annul?, target
663 | CALL Imm Int Bool -- target, args, terminal
670 riZero (RIImm (ImmInt 0)) = True
671 riZero (RIImm (ImmInteger 0)) = True
672 riZero (RIReg (FixedReg ILIT(0))) = True
675 #endif {- sparc_TARGET_ARCH -}