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 -}
438 Intel, in their infinite wisdom, selected a stack model for floating
439 point registers on x86. That might have made sense back in 1979 --
440 nowadays we can see it for the nonsense it really is. A stack model
441 fits poorly with the existing nativeGen infrastructure, which assumes
442 flat integer and FP register sets. Prior to this commit, nativeGen
443 could not generate correct x86 FP code -- to do so would have meant
444 somehow working the register-stack paradigm into the register
445 allocator and spiller, which sounds very difficult.
447 We have decided to cheat, and go for a simple fix which requires no
448 infrastructure modifications, at the expense of generating ropey but
449 correct FP code. All notions of the x86 FP stack and its insns have
450 been removed. Instead, we pretend (to the instruction selector and
451 register allocator) that x86 has six floating point registers, %fake0
452 .. %fake5, which can be used in the usual flat manner. We further
453 claim that x86 has floating point instructions very similar to SPARC
454 and Alpha, that is, a simple 3-operand register-register arrangement.
455 Code generation and register allocation proceed on this basis.
457 When we come to print out the final assembly, our convenient fiction
458 is converted to dismal reality. Each fake instruction is
459 independently converted to a series of real x86 instructions.
460 %fake0 .. %fake5 are mapped to %st(0) .. %st(5). To do reg-reg
461 arithmetic operations, the two operands are pushed onto the top of the
462 FP stack, the operation done, and the result copied back into the
463 relevant register. There are only six %fake registers because 2 are
464 needed for the translation, and x86 has 8 in total.
466 The translation is inefficient but is simple and it works. A cleverer
467 translation would handle a sequence of insns, simulating the FP stack
468 contents, would not impose a fixed mapping from %fake to %st regs, and
469 hopefully could avoid most of the redundant reg-reg moves of the
475 -- data Instr continues...
479 | MOV Size Operand Operand
480 | MOVZX Size Operand Operand -- size is the size of operand 2
481 | MOVSX Size Operand Operand -- size is the size of operand 2
483 -- Load effective address (also a very useful three-operand add instruction :-)
485 | LEA Size Operand Operand
489 | ADD Size Operand Operand
490 | SUB Size Operand Operand
492 -- Multiplication (signed and unsigned), Division (signed and unsigned),
493 -- result in %eax, %edx.
495 | IMUL Size Operand Operand
498 -- Simple bit-twiddling.
500 | AND Size Operand Operand
501 | OR Size Operand Operand
502 | XOR Size Operand Operand
504 | NEGI Size Operand -- NEG instruction (name clash with Cond)
505 | SHL Size Operand Operand -- 1st operand must be an Imm or CL
506 | SAR Size Operand Operand -- 1st operand must be an Imm or CL
507 | SHR Size Operand Operand -- 1st operand must be an Imm or CL
510 -- Float Arithmetic. -- ToDo for 386
512 -- Note that we cheat by treating G{ABS,MOV,NEG} of doubles as single instructions
513 -- right up until we spit them out.
515 -- all the 3-operand fake fp insns are src1 src2 dst
516 -- and furthermore are constrained to be fp regs only.
517 | GMOV Reg Reg -- src(fpreg), dst(fpreg)
518 | GLD Size MachRegsAddr Reg -- src, dst(fpreg)
519 | GST Size Reg MachRegsAddr -- src(fpreg), dst
521 | GFTOD Reg Reg -- src(fpreg), dst(fpreg)
522 | GFTOI Reg Reg -- src(fpreg), dst(intreg)
524 | GDTOF Reg Reg -- src(fpreg), dst(fpreg)
525 | GDTOI Reg Reg -- src(fpreg), dst(intreg)
527 | GITOF Reg Reg -- src(intreg), dst(fpreg)
528 | GITOD Reg Reg -- src(intreg), dst(fpreg)
530 | GADD Size Reg Reg Reg -- src1, src2, dst
531 | GDIV Size Reg Reg Reg -- src1, src2, dst
532 | GSUB Size Reg Reg Reg -- src1, src2, dst
533 | GMUL Size Reg Reg Reg -- src1, src2, dst
535 | GCMP Size Reg Reg -- src1, src2
537 | GABS Size Reg Reg -- src, dst
538 | GNEG Size Reg Reg -- src, dst
539 | GSQRT Size Reg Reg -- src, dst
543 | TEST Size Operand Operand
544 | CMP Size Operand Operand
556 | JMP Operand -- target
557 | JXX Cond CLabel -- target
562 | CLTD -- sign extend %eax into %edx:%eax
565 = OpReg Reg -- register
566 | OpImm Imm -- immediate value
567 | OpAddr MachRegsAddr -- memory reference
569 #endif {- i386_TARGET_ARCH -}
573 #if sparc_TARGET_ARCH
575 -- data Instr continues...
579 | LD Size MachRegsAddr Reg -- size, src, dst
580 | ST Size Reg MachRegsAddr -- size, src, dst
584 | ADD Bool Bool Reg RI Reg -- x?, cc?, src1, src2, dst
585 | SUB Bool Bool Reg RI Reg -- x?, cc?, src1, src2, dst
587 -- Simple bit-twiddling.
589 | AND Bool Reg RI Reg -- cc?, src1, src2, dst
590 | ANDN Bool Reg RI Reg -- cc?, src1, src2, dst
591 | OR Bool Reg RI Reg -- cc?, src1, src2, dst
592 | ORN Bool Reg RI Reg -- cc?, src1, src2, dst
593 | XOR Bool Reg RI Reg -- cc?, src1, src2, dst
594 | XNOR Bool Reg RI Reg -- cc?, src1, src2, dst
595 | SLL Reg RI Reg -- src1, src2, dst
596 | SRL Reg RI Reg -- src1, src2, dst
597 | SRA Reg RI Reg -- src1, src2, dst
598 | SETHI Imm Reg -- src, dst
599 | NOP -- Really SETHI 0, %g0, but worth an alias
603 -- Note that we cheat by treating F{ABS,MOV,NEG} of doubles as single instructions
604 -- right up until we spit them out.
606 | FABS Size Reg Reg -- src dst
607 | FADD Size Reg Reg Reg -- src1, src2, dst
608 | FCMP Bool Size Reg Reg -- exception?, src1, src2, dst
609 | FDIV Size Reg Reg Reg -- src1, src2, dst
610 | FMOV Size Reg Reg -- src, dst
611 | FMUL Size Reg Reg Reg -- src1, src2, dst
612 | FNEG Size Reg Reg -- src, dst
613 | FSQRT Size Reg Reg -- src, dst
614 | FSUB Size Reg Reg Reg -- src1, src2, dst
615 | FxTOy Size Size Reg Reg -- src, dst
619 | BI Cond Bool Imm -- cond, annul?, target
620 | BF Cond Bool Imm -- cond, annul?, target
622 | JMP MachRegsAddr -- target
623 | CALL Imm Int Bool -- target, args, terminal
630 riZero (RIImm (ImmInt 0)) = True
631 riZero (RIImm (ImmInteger 0)) = True
632 riZero (RIReg (FixedReg ILIT(0))) = True
635 #endif {- sparc_TARGET_ARCH -}