2 % (c) The AQUA Project, Glasgow University, 1993-1998
4 \section[MachMisc]{Description of various machine-specific things}
7 #include "nativeGen/NCG.h"
11 sizeOf, primRepToSize,
15 volatileSaves, volatileRestores,
17 targetMaxDouble, targetMaxInt, targetMinDouble, targetMinInt,
24 Instr(..), IF_ARCH_i386(Operand(..) COMMA,)
38 #include "HsVersions.h"
39 -- #include "config.h"
41 import AbsCSyn ( MagicId(..) )
42 import AbsCUtils ( magicIdPrimRep )
43 import CLabel ( CLabel )
44 import Const ( mkMachInt, Literal(..) )
45 import MachRegs ( stgReg, callerSaves, RegLoc(..),
49 import PrimRep ( PrimRep(..) )
50 import SMRep ( SMRep(..) )
51 import Stix ( StixTree(..), StixReg(..), CodeSegment )
52 import Panic ( panic )
53 import Char ( isDigit )
54 import GlaExts ( word2Int#, int2Word#, shiftRL#, and#, (/=#) )
58 underscorePrefix :: Bool -- leading underscore on assembler labels?
60 #ifdef LEADING_UNDERSCORE
61 underscorePrefix = True
63 underscorePrefix = False
66 ---------------------------
67 fmtAsmLbl :: String -> String -- for formatting labels
71 {- The alpha assembler likes temporary labels to look like $L123
72 instead of L123. (Don't toss the L, because then Lf28
80 ---------------------------
81 cvtLitLit :: String -> String
84 -- Rather than relying on guessing, use FILE_SIZE to compute the
87 cvtLitLit "stdin" = IF_ARCH_alpha("_iob+0" {-probably OK...-}
88 ,IF_ARCH_i386("_IO_stdin_"
89 ,IF_ARCH_sparc("__iob+0x0"{-probably OK...-}
92 cvtLitLit "stdout" = IF_ARCH_alpha("_iob+"++show (``FILE_SIZE''::Int)
93 ,IF_ARCH_i386("_IO_stdout_"
94 ,IF_ARCH_sparc("__iob+"++show (``FILE_SIZE''::Int)
96 cvtLitLit "stderr" = IF_ARCH_alpha("_iob+"++show (2*(``FILE_SIZE''::Int))
97 ,IF_ARCH_i386("_IO_stderr_"
98 ,IF_ARCH_sparc("__iob+"++show (2*(``FILE_SIZE''::Int))
101 cvtLitLit "stdout" = IF_ARCH_alpha("_iob+56"{-dodgy *at best*...-}
102 ,IF_ARCH_i386("_IO_stdout_"
103 ,IF_ARCH_sparc("__iob+0x10"{-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+0x20"{-dodgy *at best*...-}
112 | otherwise = error ("Native code generator can't handle ``" ++ s ++ "''")
114 isHex ('0':'x':xs) = all isHexDigit xs
116 -- Now, where have I seen this before?
117 isHexDigit c = isDigit c || c >= 'A' && c <= 'F' || c >= 'a' && c <= 'f'
120 % ----------------------------------------------------------------
122 We (allegedly) put the first six C-call arguments in registers;
123 where do we start putting the rest of them?
125 eXTRA_STK_ARGS_HERE :: Int
127 = IF_ARCH_alpha(0, IF_ARCH_i386(23{-6x4bytes-}, IF_ARCH_sparc(23,???)))
130 % - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
132 Size of a @PrimRep@, in bytes.
135 sizeOf :: PrimRep -> Integer{-in bytes-}
136 -- the result is an Integer only because it's more convenient
138 sizeOf pr = case (primRepToSize pr) of
139 IF_ARCH_alpha({B -> 1; BU -> 1; {-W -> 2; WU -> 2; L -> 4; SF -> 4;-} _ -> 8},)
140 IF_ARCH_sparc({B -> 1; BU -> 1; {-HW -> 2; HWU -> 2;-} W -> 4; {-D -> 8;-} F -> 4; DF -> 8},)
141 IF_ARCH_i386( {B -> 1; {-S -> 2;-} L -> 4; F -> 4; DF -> 8 },)
144 % - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
146 Now the volatile saves and restores. We add the basic guys to the
147 list of ``user'' registers provided. Note that there are more basic
148 registers on the restore list, because some are reloaded from
151 (@volatileRestores@ used only for wrapper-hungry PrimOps.)
154 volatileSaves, volatileRestores :: [MagicId] -> [StixTree]
156 save_cands = [BaseReg,Sp,Su,SpLim,Hp,HpLim]
157 restore_cands = save_cands
160 = map save ((filter callerSaves) (save_cands ++ vols))
162 save x = StAssign (magicIdPrimRep x) loc reg
164 reg = StReg (StixMagicId x)
165 loc = case stgReg x of
167 Always _ -> panic "volatileSaves"
169 volatileRestores vols
170 = map restore ((filter callerSaves) (restore_cands ++ vols))
172 restore x = StAssign (magicIdPrimRep x) reg loc
174 reg = StReg (StixMagicId x)
175 loc = case stgReg x of
177 Always _ -> panic "volatileRestores"
180 % - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
182 Obviously slightly weedy
183 (Note that the floating point values aren't terribly important.)
186 targetMinDouble = MachDouble (-1.7976931348623157e+308)
187 targetMaxDouble = MachDouble (1.7976931348623157e+308)
188 targetMinInt = mkMachInt (-2147483648)
189 targetMaxInt = mkMachInt 2147483647
192 % - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
194 This algorithm for determining the $\log_2$ of exact powers of 2 comes
195 from GCC. It requires bit manipulation primitives, and we use GHC
202 exactLog2 :: Integer -> Maybe Integer
204 = if (x <= 0 || x >= 2147483648) then
207 case (fromInteger x) of { I# x# ->
208 if (w2i ((i2w x#) `and#` (i2w (0# -# x#))) /=# x#) then
211 Just (toInteger (I# (pow2 x#)))
214 shiftr x y = shiftRL# x y
216 pow2 x# | x# ==# 1# = 0#
217 | otherwise = 1# +# pow2 (w2i (i2w x# `shiftr` 1#))
220 % - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
224 #if alpha_TARGET_ARCH
225 = ALWAYS -- For BI (same as BR)
226 | EQQ -- For CMP and BI (NB: "EQ" is a 1.3 Prelude name)
228 | GTT -- For BI only (NB: "GT" is a 1.3 Prelude name)
229 | LE -- For CMP and BI
230 | LTT -- For CMP and BI (NB: "LT" is a 1.3 Prelude name)
232 | NEVER -- For BI (null instruction)
233 | ULE -- For CMP only
234 | ULT -- For CMP only
237 = ALWAYS -- What's really used? ToDo
251 #if sparc_TARGET_ARCH
252 = ALWAYS -- What's really used? ToDo
273 #if alpha_TARGET_ARCH
276 -- | W -- word (2 bytes): UNUSED
278 -- | L -- longword (4 bytes): UNUSED
279 | Q -- quadword (8 bytes)
280 -- | FF -- VAX F-style floating pt: UNUSED
281 -- | GF -- VAX G-style floating pt: UNUSED
282 -- | DF -- VAX D-style floating pt: UNUSED
283 -- | SF -- IEEE single-precision floating pt: UNUSED
284 | TF -- IEEE double-precision floating pt
288 -- | HB -- higher byte **UNUSED**
291 | F -- IEEE single-precision floating pt
292 | DF -- IEEE single-precision floating pt
294 #if sparc_TARGET_ARCH
296 | BU -- byte (unsigned)
297 -- | HW -- halfword, 2 bytes (signed): UNUSED
298 -- | HWU -- halfword, 2 bytes (unsigned): UNUSED
300 -- | D -- doubleword, 8 bytes: UNUSED
301 | F -- IEEE single-precision floating pt
302 | DF -- IEEE single-precision floating pt
305 primRepToSize :: PrimRep -> Size
307 primRepToSize PtrRep = IF_ARCH_alpha( Q, IF_ARCH_i386( L, IF_ARCH_sparc( W ,)))
308 primRepToSize CodePtrRep = IF_ARCH_alpha( Q, IF_ARCH_i386( L, IF_ARCH_sparc( W ,)))
309 primRepToSize DataPtrRep = IF_ARCH_alpha( Q, IF_ARCH_i386( L, IF_ARCH_sparc( W ,)))
310 primRepToSize RetRep = IF_ARCH_alpha( Q, IF_ARCH_i386( L, IF_ARCH_sparc( W ,)))
311 primRepToSize CostCentreRep = IF_ARCH_alpha( Q, IF_ARCH_i386( L, IF_ARCH_sparc( W ,)))
312 primRepToSize CharRep = IF_ARCH_alpha( BU, IF_ARCH_i386( L, IF_ARCH_sparc( BU,)))
313 primRepToSize IntRep = IF_ARCH_alpha( Q, IF_ARCH_i386( L, IF_ARCH_sparc( W ,)))
314 primRepToSize WordRep = IF_ARCH_alpha( Q, IF_ARCH_i386( L, IF_ARCH_sparc( W ,)))
315 primRepToSize AddrRep = IF_ARCH_alpha( Q, IF_ARCH_i386( L, IF_ARCH_sparc( W ,)))
316 primRepToSize FloatRep = IF_ARCH_alpha( TF, IF_ARCH_i386( F, IF_ARCH_sparc( F ,)))
317 primRepToSize DoubleRep = IF_ARCH_alpha( TF, IF_ARCH_i386( DF,IF_ARCH_sparc( DF,)))
318 primRepToSize ArrayRep = IF_ARCH_alpha( Q, IF_ARCH_i386( L, IF_ARCH_sparc( W ,)))
319 primRepToSize ByteArrayRep = IF_ARCH_alpha( Q, IF_ARCH_i386( L, IF_ARCH_sparc( W ,)))
320 primRepToSize WeakPtrRep = IF_ARCH_alpha( Q, IF_ARCH_i386( L, IF_ARCH_sparc( W ,)))
321 primRepToSize ForeignObjRep = IF_ARCH_alpha( Q, IF_ARCH_i386( L, IF_ARCH_sparc( W ,)))
322 primRepToSize StablePtrRep = IF_ARCH_alpha( Q, IF_ARCH_i386( L, IF_ARCH_sparc( W ,)))
325 %************************************************************************
327 \subsection{Machine's assembly language}
329 %************************************************************************
331 We have a few common ``instructions'' (nearly all the pseudo-ops) but
332 mostly all of @Instr@ is machine-specific.
336 = COMMENT FAST_STRING -- comment pseudo-op
337 | SEGMENT CodeSegment -- {data,text} segment pseudo-op
338 | LABEL CLabel -- global label pseudo-op
339 | ASCII Bool -- True <=> needs backslash conversion
340 String -- the literal string
346 #if alpha_TARGET_ARCH
348 -- data Instr continues...
352 | LD Size Reg MachRegsAddr -- size, dst, src
353 | LDA Reg MachRegsAddr -- dst, src
354 | LDAH Reg MachRegsAddr -- dst, src
355 | LDGP Reg MachRegsAddr -- dst, src
356 | LDI Size Reg Imm -- size, dst, src
357 | ST Size Reg MachRegsAddr -- size, src, dst
362 | ABS Size RI Reg -- size, src, dst
363 | NEG Size Bool RI Reg -- size, overflow, src, dst
364 | ADD Size Bool Reg RI Reg -- size, overflow, src, src, dst
365 | SADD Size Size Reg RI Reg -- size, scale, src, src, dst
366 | SUB Size Bool Reg RI Reg -- size, overflow, src, src, dst
367 | SSUB Size Size Reg RI Reg -- size, scale, src, src, dst
368 | MUL Size Bool Reg RI Reg -- size, overflow, src, src, dst
369 | DIV Size Bool Reg RI Reg -- size, unsigned, src, src, dst
370 | REM Size Bool Reg RI Reg -- size, unsigned, src, src, dst
372 -- Simple bit-twiddling.
392 | CMP Cond Reg RI Reg
399 | FADD Size Reg Reg Reg
400 | FDIV Size Reg Reg Reg
401 | FMUL Size Reg Reg Reg
402 | FSUB Size Reg Reg Reg
403 | CVTxy Size Size Reg Reg
404 | FCMP Size Cond Reg Reg Reg
412 | JMP Reg MachRegsAddr Int
414 | JSR Reg MachRegsAddr Int
416 -- Alpha-specific pseudo-ops.
425 #endif {- alpha_TARGET_ARCH -}
431 -- data Instr continues...
435 | MOV Size Operand Operand
436 | MOVZX Size Operand Operand -- size is the size of operand 2
437 | MOVSX Size Operand Operand -- size is the size of operand 2
439 -- Load effective address (also a very useful three-operand add instruction :-)
441 | LEA Size Operand Operand
445 | ADD Size Operand Operand
446 | SUB Size Operand Operand
448 -- Multiplication (signed and unsigned), Division (signed and unsigned),
449 -- result in %eax, %edx.
451 | IMUL Size Operand Operand
454 -- Simple bit-twiddling.
456 | AND Size Operand Operand
457 | OR Size Operand Operand
458 | XOR Size Operand Operand
460 | NEGI Size Operand -- NEG instruction (name clash with Cond)
461 | SHL Size Operand Operand -- 1st operand must be an Imm or CL
462 | SAR Size Operand Operand -- 1st operand must be an Imm or CL
463 | SHR Size Operand Operand -- 1st operand must be an Imm or CL
466 -- Float Arithmetic. -- ToDo for 386
468 -- Note that we cheat by treating F{ABS,MOV,NEG} of doubles as single instructions
469 -- right up until we spit them out.
471 | SAHF -- stores ah into flags
473 | FADD Size Operand -- src
475 | FIADD Size MachRegsAddr -- src
477 | FCOM Size Operand -- src
479 | FDIV Size Operand -- src
481 | FIDIV Size MachRegsAddr -- src
482 | FDIVR Size Operand -- src
484 | FIDIVR Size MachRegsAddr -- src
485 | FICOM Size MachRegsAddr -- src
486 | FILD Size MachRegsAddr Reg -- src, dst
487 | FIST Size MachRegsAddr -- dst
488 | FLD Size Operand -- src
491 | FMUL Size Operand -- src
493 | FIMUL Size MachRegsAddr -- src
497 | FST Size Operand -- dst
498 | FSTP Size Operand -- dst
499 | FSUB Size Operand -- src
501 | FISUB Size MachRegsAddr -- src
502 | FSUBR Size Operand -- src
504 | FISUBR Size MachRegsAddr -- src
506 | FCOMP Size Operand -- src
514 | TEST Size Operand Operand
515 | CMP Size Operand Operand
525 | JMP Operand -- target
526 | JXX Cond CLabel -- target
531 | CLTD -- sign extend %eax into %edx:%eax
534 = OpReg Reg -- register
535 | OpImm Imm -- immediate value
536 | OpAddr MachRegsAddr -- memory reference
538 #endif {- i386_TARGET_ARCH -}
542 #if sparc_TARGET_ARCH
544 -- data Instr continues...
548 | LD Size MachRegsAddr Reg -- size, src, dst
549 | ST Size Reg MachRegsAddr -- size, src, dst
553 | ADD Bool Bool Reg RI Reg -- x?, cc?, src1, src2, dst
554 | SUB Bool Bool Reg RI Reg -- x?, cc?, src1, src2, dst
556 -- Simple bit-twiddling.
558 | AND Bool Reg RI Reg -- cc?, src1, src2, dst
559 | ANDN Bool Reg RI Reg -- cc?, src1, src2, dst
560 | OR Bool Reg RI Reg -- cc?, src1, src2, dst
561 | ORN Bool Reg RI Reg -- cc?, src1, src2, dst
562 | XOR Bool Reg RI Reg -- cc?, src1, src2, dst
563 | XNOR Bool Reg RI Reg -- cc?, src1, src2, dst
564 | SLL Reg RI Reg -- src1, src2, dst
565 | SRL Reg RI Reg -- src1, src2, dst
566 | SRA Reg RI Reg -- src1, src2, dst
567 | SETHI Imm Reg -- src, dst
568 | NOP -- Really SETHI 0, %g0, but worth an alias
572 -- Note that we cheat by treating F{ABS,MOV,NEG} of doubles as single instructions
573 -- right up until we spit them out.
575 | FABS Size Reg Reg -- src dst
576 | FADD Size Reg Reg Reg -- src1, src2, dst
577 | FCMP Bool Size Reg Reg -- exception?, src1, src2, dst
578 | FDIV Size Reg Reg Reg -- src1, src2, dst
579 | FMOV Size Reg Reg -- src, dst
580 | FMUL Size Reg Reg Reg -- src1, src2, dst
581 | FNEG Size Reg Reg -- src, dst
582 | FSQRT Size Reg Reg -- src, dst
583 | FSUB Size Reg Reg Reg -- src1, src2, dst
584 | FxTOy Size Size Reg Reg -- src, dst
588 | BI Cond Bool Imm -- cond, annul?, target
589 | BF Cond Bool Imm -- cond, annul?, target
591 | JMP MachRegsAddr -- target
592 | CALL Imm Int Bool -- target, args, terminal
599 riZero (RIImm (ImmInt 0)) = True
600 riZero (RIImm (ImmInteger 0)) = True
601 riZero (RIReg (FixedReg ILIT(0))) = True
604 #endif {- sparc_TARGET_ARCH -}