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,
23 stixFor_stdout, stixFor_stderr, stixFor_stdin,
25 Instr(..), IF_ARCH_i386(Operand(..) COMMA,)
39 #include "HsVersions.h"
40 -- #include "config.h"
42 import AbsCSyn ( MagicId(..) )
43 import AbsCUtils ( magicIdPrimRep )
44 import CLabel ( CLabel )
45 import Const ( mkMachInt, Literal(..) )
46 import MachRegs ( stgReg, callerSaves, RegLoc(..),
50 import PrimRep ( PrimRep(..) )
51 import SMRep ( SMRep(..) )
52 import Stix ( StixTree(..), StixReg(..), CodeSegment )
53 import Panic ( panic )
54 import Char ( isDigit )
55 import GlaExts ( word2Int#, int2Word#, shiftRL#, and#, (/=#) )
56 import Outputable ( text )
60 underscorePrefix :: Bool -- leading underscore on assembler labels?
62 #ifdef LEADING_UNDERSCORE
63 underscorePrefix = True
65 underscorePrefix = False
68 ---------------------------
69 fmtAsmLbl :: String -> String -- for formatting labels
73 {- The alpha assembler likes temporary labels to look like $L123
74 instead of L123. (Don't toss the L, because then Lf28
82 ---------------------------
83 stixFor_stdout, stixFor_stderr, stixFor_stdin :: StixTree
85 -- Linux glibc 2 / libc6
86 stixFor_stdout = StInd PtrRep (StLitLbl (text "stdout"))
87 stixFor_stderr = StInd PtrRep (StLitLbl (text "stderr"))
88 stixFor_stdin = StInd PtrRep (StLitLbl (text "stdin"))
92 stixFor_stdout = error "stixFor_stdout: not implemented for Alpha"
93 stixFor_stderr = error "stixFor_stderr: not implemented for Alpha"
94 stixFor_stdin = error "stixFor_stdin: not implemented for Alpha"
98 stixFor_stdout = error "stixFor_stdout: not implemented for Sparc"
99 stixFor_stderr = error "stixFor_stderr: not implemented for Sparc"
100 stixFor_stdin = error "stixFor_stdin: not implemented for Sparc"
104 Here's some old stuff from which it shouldn't be too hard to
105 implement the above for Alpha/Sparc.
107 cvtLitLit :: String -> String
110 -- Rather than relying on guessing, use FILE_SIZE to compute the
113 cvtLitLit "stdin" = IF_ARCH_alpha("_iob+0" {-probably OK...-}
114 ,IF_ARCH_i386("stdin"
115 ,IF_ARCH_sparc("__iob+0x0"{-probably OK...-}
118 cvtLitLit "stdout" = IF_ARCH_alpha("_iob+"++show (``FILE_SIZE''::Int)
119 ,IF_ARCH_i386("stdout"
120 ,IF_ARCH_sparc("__iob+"++show (``FILE_SIZE''::Int)
122 cvtLitLit "stderr" = IF_ARCH_alpha("_iob+"++show (2*(``FILE_SIZE''::Int))
123 ,IF_ARCH_i386("stderr"
124 ,IF_ARCH_sparc("__iob+"++show (2*(``FILE_SIZE''::Int))
130 % ----------------------------------------------------------------
132 We (allegedly) put the first six C-call arguments in registers;
133 where do we start putting the rest of them?
135 eXTRA_STK_ARGS_HERE :: Int
137 = IF_ARCH_alpha(0, IF_ARCH_i386(23{-6x4bytes-}, IF_ARCH_sparc(23,???)))
140 % - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
142 Size of a @PrimRep@, in bytes.
145 sizeOf :: PrimRep -> Integer{-in bytes-}
146 -- the result is an Integer only because it's more convenient
148 sizeOf pr = case (primRepToSize pr) of
149 IF_ARCH_alpha({B -> 1; BU -> 1; {-W -> 2; WU -> 2; L -> 4; SF -> 4;-} _ -> 8},)
150 IF_ARCH_sparc({B -> 1; BU -> 1; {-HW -> 2; HWU -> 2;-} W -> 4; {-D -> 8;-} F -> 4; DF -> 8},)
151 IF_ARCH_i386( {B -> 1; {-S -> 2;-} L -> 4; F -> 4; DF -> 8 },)
154 % - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
156 Now the volatile saves and restores. We add the basic guys to the
157 list of ``user'' registers provided. Note that there are more basic
158 registers on the restore list, because some are reloaded from
161 (@volatileRestores@ used only for wrapper-hungry PrimOps.)
164 volatileSaves, volatileRestores :: [MagicId] -> [StixTree]
166 save_cands = [BaseReg,Sp,Su,SpLim,Hp,HpLim]
167 restore_cands = save_cands
170 = map save ((filter callerSaves) (save_cands ++ vols))
172 save x = StAssign (magicIdPrimRep x) loc reg
174 reg = StReg (StixMagicId x)
175 loc = case stgReg x of
177 Always _ -> panic "volatileSaves"
179 volatileRestores vols
180 = map restore ((filter callerSaves) (restore_cands ++ vols))
182 restore x = StAssign (magicIdPrimRep x) reg loc
184 reg = StReg (StixMagicId x)
185 loc = case stgReg x of
187 Always _ -> panic "volatileRestores"
190 % - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
192 Obviously slightly weedy
193 (Note that the floating point values aren't terribly important.)
196 targetMinDouble = MachDouble (-1.7976931348623157e+308)
197 targetMaxDouble = MachDouble (1.7976931348623157e+308)
198 targetMinInt = mkMachInt (-2147483648)
199 targetMaxInt = mkMachInt 2147483647
202 % - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
204 This algorithm for determining the $\log_2$ of exact powers of 2 comes
205 from GCC. It requires bit manipulation primitives, and we use GHC
212 exactLog2 :: Integer -> Maybe Integer
214 = if (x <= 0 || x >= 2147483648) then
217 case (fromInteger x) of { I# x# ->
218 if (w2i ((i2w x#) `and#` (i2w (0# -# x#))) /=# x#) then
221 Just (toInteger (I# (pow2 x#)))
224 shiftr x y = shiftRL# x y
226 pow2 x# | x# ==# 1# = 0#
227 | otherwise = 1# +# pow2 (w2i (i2w x# `shiftr` 1#))
230 % - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
234 #if alpha_TARGET_ARCH
235 = ALWAYS -- For BI (same as BR)
236 | EQQ -- For CMP and BI (NB: "EQ" is a 1.3 Prelude name)
238 | GTT -- For BI only (NB: "GT" is a 1.3 Prelude name)
239 | LE -- For CMP and BI
240 | LTT -- For CMP and BI (NB: "LT" is a 1.3 Prelude name)
242 | NEVER -- For BI (null instruction)
243 | ULE -- For CMP only
244 | ULT -- For CMP only
247 = ALWAYS -- What's really used? ToDo
261 #if sparc_TARGET_ARCH
262 = ALWAYS -- What's really used? ToDo
283 #if alpha_TARGET_ARCH
286 -- | W -- word (2 bytes): UNUSED
288 -- | L -- longword (4 bytes): UNUSED
289 | Q -- quadword (8 bytes)
290 -- | FF -- VAX F-style floating pt: UNUSED
291 -- | GF -- VAX G-style floating pt: UNUSED
292 -- | DF -- VAX D-style floating pt: UNUSED
293 -- | SF -- IEEE single-precision floating pt: UNUSED
294 | TF -- IEEE double-precision floating pt
298 -- | HB -- higher byte **UNUSED**
301 | F -- IEEE single-precision floating pt
302 | DF -- IEEE single-precision floating pt
304 #if sparc_TARGET_ARCH
306 | BU -- byte (unsigned)
307 -- | HW -- halfword, 2 bytes (signed): UNUSED
308 -- | HWU -- halfword, 2 bytes (unsigned): UNUSED
310 -- | D -- doubleword, 8 bytes: UNUSED
311 | F -- IEEE single-precision floating pt
312 | DF -- IEEE single-precision floating pt
315 primRepToSize :: PrimRep -> Size
317 primRepToSize PtrRep = IF_ARCH_alpha( Q, IF_ARCH_i386( L, IF_ARCH_sparc( W ,)))
318 primRepToSize CodePtrRep = IF_ARCH_alpha( Q, IF_ARCH_i386( L, IF_ARCH_sparc( W ,)))
319 primRepToSize DataPtrRep = IF_ARCH_alpha( Q, IF_ARCH_i386( L, IF_ARCH_sparc( W ,)))
320 primRepToSize RetRep = IF_ARCH_alpha( Q, IF_ARCH_i386( L, IF_ARCH_sparc( W ,)))
321 primRepToSize CostCentreRep = IF_ARCH_alpha( Q, IF_ARCH_i386( L, IF_ARCH_sparc( W ,)))
322 primRepToSize CharRep = IF_ARCH_alpha( BU, IF_ARCH_i386( L, IF_ARCH_sparc( BU,)))
323 primRepToSize IntRep = IF_ARCH_alpha( Q, IF_ARCH_i386( L, IF_ARCH_sparc( W ,)))
324 primRepToSize WordRep = IF_ARCH_alpha( Q, IF_ARCH_i386( L, IF_ARCH_sparc( W ,)))
325 primRepToSize AddrRep = IF_ARCH_alpha( Q, IF_ARCH_i386( L, IF_ARCH_sparc( W ,)))
326 primRepToSize FloatRep = IF_ARCH_alpha( TF, IF_ARCH_i386( F, IF_ARCH_sparc( F ,)))
327 primRepToSize DoubleRep = IF_ARCH_alpha( TF, IF_ARCH_i386( DF,IF_ARCH_sparc( DF,)))
328 primRepToSize ArrayRep = IF_ARCH_alpha( Q, IF_ARCH_i386( L, IF_ARCH_sparc( W ,)))
329 primRepToSize ByteArrayRep = IF_ARCH_alpha( Q, IF_ARCH_i386( L, IF_ARCH_sparc( W ,)))
330 primRepToSize WeakPtrRep = IF_ARCH_alpha( Q, IF_ARCH_i386( L, IF_ARCH_sparc( W ,)))
331 primRepToSize ForeignObjRep = IF_ARCH_alpha( Q, IF_ARCH_i386( L, IF_ARCH_sparc( W ,)))
332 primRepToSize StablePtrRep = IF_ARCH_alpha( Q, IF_ARCH_i386( L, IF_ARCH_sparc( W ,)))
335 %************************************************************************
337 \subsection{Machine's assembly language}
339 %************************************************************************
341 We have a few common ``instructions'' (nearly all the pseudo-ops) but
342 mostly all of @Instr@ is machine-specific.
346 = COMMENT FAST_STRING -- comment pseudo-op
347 | SEGMENT CodeSegment -- {data,text} segment pseudo-op
348 | LABEL CLabel -- global label pseudo-op
349 | ASCII Bool -- True <=> needs backslash conversion
350 String -- the literal string
356 #if alpha_TARGET_ARCH
358 -- data Instr continues...
362 | LD Size Reg MachRegsAddr -- size, dst, src
363 | LDA Reg MachRegsAddr -- dst, src
364 | LDAH Reg MachRegsAddr -- dst, src
365 | LDGP Reg MachRegsAddr -- dst, src
366 | LDI Size Reg Imm -- size, dst, src
367 | ST Size Reg MachRegsAddr -- size, src, dst
372 | ABS Size RI Reg -- size, src, dst
373 | NEG Size Bool RI Reg -- size, overflow, src, dst
374 | ADD Size Bool Reg RI Reg -- size, overflow, src, src, dst
375 | SADD Size Size Reg RI Reg -- size, scale, src, src, dst
376 | SUB Size Bool Reg RI Reg -- size, overflow, src, src, dst
377 | SSUB Size Size Reg RI Reg -- size, scale, src, src, dst
378 | MUL Size Bool Reg RI Reg -- size, overflow, src, src, dst
379 | DIV Size Bool Reg RI Reg -- size, unsigned, src, src, dst
380 | REM Size Bool Reg RI Reg -- size, unsigned, src, src, dst
382 -- Simple bit-twiddling.
402 | CMP Cond Reg RI Reg
409 | FADD Size Reg Reg Reg
410 | FDIV Size Reg Reg Reg
411 | FMUL Size Reg Reg Reg
412 | FSUB Size Reg Reg Reg
413 | CVTxy Size Size Reg Reg
414 | FCMP Size Cond Reg Reg Reg
422 | JMP Reg MachRegsAddr Int
424 | JSR Reg MachRegsAddr Int
426 -- Alpha-specific pseudo-ops.
435 #endif {- alpha_TARGET_ARCH -}
441 -- data Instr continues...
445 | MOV Size Operand Operand
446 | MOVZX Size Operand Operand -- size is the size of operand 2
447 | MOVSX Size Operand Operand -- size is the size of operand 2
449 -- Load effective address (also a very useful three-operand add instruction :-)
451 | LEA Size Operand Operand
455 | ADD Size Operand Operand
456 | SUB Size Operand Operand
458 -- Multiplication (signed and unsigned), Division (signed and unsigned),
459 -- result in %eax, %edx.
461 | IMUL Size Operand Operand
464 -- Simple bit-twiddling.
466 | AND Size Operand Operand
467 | OR Size Operand Operand
468 | XOR Size Operand Operand
470 | NEGI Size Operand -- NEG instruction (name clash with Cond)
471 | SHL Size Operand Operand -- 1st operand must be an Imm or CL
472 | SAR Size Operand Operand -- 1st operand must be an Imm or CL
473 | SHR Size Operand Operand -- 1st operand must be an Imm or CL
476 -- Float Arithmetic. -- ToDo for 386
478 -- Note that we cheat by treating F{ABS,MOV,NEG} of doubles as single instructions
479 -- right up until we spit them out.
481 | SAHF -- stores ah into flags
483 | FADD Size Operand -- src
485 | FIADD Size MachRegsAddr -- src
487 | FCOM Size Operand -- src
489 | FDIV Size Operand -- src
491 | FIDIV Size MachRegsAddr -- src
492 | FDIVR Size Operand -- src
494 | FIDIVR Size MachRegsAddr -- src
495 | FICOM Size MachRegsAddr -- src
496 | FILD Size MachRegsAddr Reg -- src, dst
497 | FIST Size MachRegsAddr -- dst
498 | FLD Size Operand -- src
501 | FMUL Size Operand -- src
503 | FIMUL Size MachRegsAddr -- src
507 | FST Size Operand -- dst
508 | FSTP Size Operand -- dst
509 | FSUB Size Operand -- src
511 | FISUB Size MachRegsAddr -- src
512 | FSUBR Size Operand -- src
514 | FISUBR Size MachRegsAddr -- src
516 | FCOMP Size Operand -- src
524 | TEST Size Operand Operand
525 | CMP Size Operand Operand
537 | JMP Operand -- target
538 | JXX Cond CLabel -- target
543 | CLTD -- sign extend %eax into %edx:%eax
546 = OpReg Reg -- register
547 | OpImm Imm -- immediate value
548 | OpAddr MachRegsAddr -- memory reference
550 #endif {- i386_TARGET_ARCH -}
554 #if sparc_TARGET_ARCH
556 -- data Instr continues...
560 | LD Size MachRegsAddr Reg -- size, src, dst
561 | ST Size Reg MachRegsAddr -- size, src, dst
565 | ADD Bool Bool Reg RI Reg -- x?, cc?, src1, src2, dst
566 | SUB Bool Bool Reg RI Reg -- x?, cc?, src1, src2, dst
568 -- Simple bit-twiddling.
570 | AND Bool Reg RI Reg -- cc?, src1, src2, dst
571 | ANDN Bool Reg RI Reg -- cc?, src1, src2, dst
572 | OR Bool Reg RI Reg -- cc?, src1, src2, dst
573 | ORN Bool Reg RI Reg -- cc?, src1, src2, dst
574 | XOR Bool Reg RI Reg -- cc?, src1, src2, dst
575 | XNOR Bool Reg RI Reg -- cc?, src1, src2, dst
576 | SLL Reg RI Reg -- src1, src2, dst
577 | SRL Reg RI Reg -- src1, src2, dst
578 | SRA Reg RI Reg -- src1, src2, dst
579 | SETHI Imm Reg -- src, dst
580 | NOP -- Really SETHI 0, %g0, but worth an alias
584 -- Note that we cheat by treating F{ABS,MOV,NEG} of doubles as single instructions
585 -- right up until we spit them out.
587 | FABS Size Reg Reg -- src dst
588 | FADD Size Reg Reg Reg -- src1, src2, dst
589 | FCMP Bool Size Reg Reg -- exception?, src1, src2, dst
590 | FDIV Size Reg Reg Reg -- src1, src2, dst
591 | FMOV Size Reg Reg -- src, dst
592 | FMUL Size Reg Reg Reg -- src1, src2, dst
593 | FNEG Size Reg Reg -- src, dst
594 | FSQRT Size Reg Reg -- src, dst
595 | FSUB Size Reg Reg Reg -- src1, src2, dst
596 | FxTOy Size Size Reg Reg -- src, dst
600 | BI Cond Bool Imm -- cond, annul?, target
601 | BF Cond Bool Imm -- cond, annul?, target
603 | JMP MachRegsAddr -- target
604 | CALL Imm Int Bool -- target, args, terminal
611 riZero (RIImm (ImmInt 0)) = True
612 riZero (RIImm (ImmInteger 0)) = True
613 riZero (RIReg (FixedReg ILIT(0))) = True
616 #endif {- sparc_TARGET_ARCH -}