[project @ 1997-08-25 21:47:18 by sof]
[ghc-hetmet.git] / ghc / compiler / nativeGen / MachMisc.lhs
1 %
2 % (c) The AQUA Project, Glasgow University, 1993-1996
3 %
4 \section[MachMisc]{Description of various machine-specific things}
5
6 \begin{code}
7 #include "HsVersions.h"
8 #include "nativeGen/NCG.h"
9
10 module MachMisc (
11
12         fixedHdrSizeInWords, varHdrSizeInWords,
13         charLikeSize, intLikeSize, mutHS, dataHS, foHS,
14         sizeOf, primRepToSize,
15
16         eXTRA_STK_ARGS_HERE,
17
18         volatileSaves, volatileRestores,
19
20         storageMgrInfo, smCAFlist, smOldLim, smOldMutables,
21         smStablePtrTable,
22
23         targetMaxDouble, targetMaxInt, targetMinDouble, targetMinInt,
24
25         underscorePrefix,
26         fmtAsmLbl,
27         cvtLitLit,
28         exactLog2,
29
30         Instr(..),  IF_ARCH_i386(Operand(..) COMMA,)
31         Cond(..),
32         Size(..)
33         
34 #if alpha_TARGET_ARCH
35         , RI(..)
36 #endif
37 #if i386_TARGET_ARCH
38 #endif
39 #if sparc_TARGET_ARCH
40         , RI(..), riZero
41 #endif
42     ) where
43
44 IMPORT_1_3(Char(isDigit))
45 IMP_Ubiq(){-uitous-}
46
47 #if defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ <= 201
48 IMPORT_DELOOPER(AbsCLoop)               ( fixedHdrSizeInWords, varHdrSizeInWords ) -- paranoia
49 IMPORT_DELOOPER(NcgLoop)                ( underscorePrefix, fmtAsmLbl ) -- paranoia
50 #endif
51
52 import AbsCSyn          ( MagicId(..) ) 
53 import AbsCUtils        ( magicIdPrimRep )
54 import CLabel           ( CLabel )
55 import CmdLineOpts      ( opt_SccProfilingOn )
56 import Literal          ( mkMachInt, Literal(..) )
57 import MachRegs         ( stgReg, callerSaves, RegLoc(..),
58                           Imm(..), Reg(..)
59 #if __GLASGOW_HASKELL__ >= 202
60                         )
61 import qualified MachRegs (Addr)
62 #define MachRegsAddr MachRegs.Addr
63 #else
64                         , Addr(..)
65                         )
66 #define MachRegsAddr Addr
67 #endif
68
69 import OrdList          ( OrdList )
70 import PrimRep          ( PrimRep(..) )
71 import SMRep            ( SMRep(..), SMSpecRepKind(..), SMUpdateKind(..) )
72 import Stix             ( StixTree(..), StixReg(..), sStLitLbl,
73                           CodeSegment
74                         )
75 import Util             ( panic )
76 \end{code}
77
78 \begin{code}
79 underscorePrefix :: Bool   -- leading underscore on labels?
80
81 underscorePrefix
82   = IF_ARCH_alpha(False
83     ,{-else-} IF_ARCH_i386(
84         IF_OS_linuxaout(True
85         , IF_OS_freebsd(True
86         , IF_OS_cygwin32(True
87         , IF_OS_bsdi(True
88         , {-otherwise-} False)))
89         )
90      ,{-else-}IF_ARCH_sparc(
91         IF_OS_sunos4(True, {-otherwise-} False)
92      ,)))
93
94 ---------------------------
95 fmtAsmLbl :: String -> String  -- for formatting labels
96
97 fmtAsmLbl s
98   =  IF_ARCH_alpha(
99      {- The alpha assembler likes temporary labels to look like $L123
100         instead of L123.  (Don't toss the L, because then Lf28
101         turns into $f28.)
102      -}
103      '$' : s
104      ,{-otherwise-}
105      s
106      )
107
108 ---------------------------
109 cvtLitLit :: String -> String
110
111 --
112 -- Rather than relying on guessing, use FILE_SIZE to compute the
113 -- _iob offsets.
114 --
115 cvtLitLit "stdin"  = IF_ARCH_alpha("_iob+0" {-probably OK...-}
116                     ,IF_ARCH_i386("_IO_stdin_"
117                     ,IF_ARCH_sparc("__iob+0x0"{-probably OK...-}
118                     ,)))
119
120 cvtLitLit "stdout" = IF_ARCH_alpha("_iob+"++show (``FILE_SIZE''::Int)
121                     ,IF_ARCH_i386("_IO_stdout_"
122                     ,IF_ARCH_sparc("__iob+"++show (``FILE_SIZE''::Int)
123                     ,)))
124 cvtLitLit "stderr" = IF_ARCH_alpha("_iob+"++show (2*(``FILE_SIZE''::Int))
125                     ,IF_ARCH_i386("_IO_stderr_"
126                     ,IF_ARCH_sparc("__iob+"++show (2*(``FILE_SIZE''::Int))
127                     ,)))
128 {-
129 cvtLitLit "stdout" = IF_ARCH_alpha("_iob+56"{-dodgy *at best*...-}
130                     ,IF_ARCH_i386("_IO_stdout_"
131                     ,IF_ARCH_sparc("__iob+0x10"{-dodgy *at best*...-}
132                     ,)))
133 cvtLitLit "stderr" = IF_ARCH_alpha("_iob+112"{-dodgy *at best*...-}
134                     ,IF_ARCH_i386("_IO_stderr_"
135                     ,IF_ARCH_sparc("__iob+0x20"{-dodgy *at best*...-}
136                     ,)))
137 -}
138 cvtLitLit s
139   | isHex s   = s
140   | otherwise = error ("Native code generator can't handle ``" ++ s ++ "''")
141   where
142     isHex ('0':'x':xs) = all isHexDigit xs
143     isHex _ = False
144     -- Now, where have I seen this before?
145     isHexDigit c = isDigit c || c >= 'A' && c <= 'F' || c >= 'a' && c <= 'f'
146 \end{code}
147
148 % ----------------------------------------------------------------
149
150 We (allegedly) put the first six C-call arguments in registers;
151 where do we start putting the rest of them?
152 \begin{code}
153 eXTRA_STK_ARGS_HERE :: Int
154 eXTRA_STK_ARGS_HERE
155   = IF_ARCH_alpha(0, IF_ARCH_i386(23{-6x4bytes-}, IF_ARCH_sparc(23,???)))
156 \end{code}
157
158 % ----------------------------------------------------------------
159
160 @fixedHdrSizeInWords@ and @varHdrSizeInWords@: these are not dependent
161 on target architecture.
162 \begin{code}
163 fixedHdrSizeInWords :: Int
164
165 fixedHdrSizeInWords
166   = 1{-info ptr-} + profFHS + parFHS + tickyFHS
167     -- obviously, we aren't taking non-sequential too seriously yet
168   where
169     profFHS  = if opt_SccProfilingOn then 1 else 0
170     parFHS   = {-if PAR or GRAN then 1 else-} 0
171     tickyFHS = {-if ticky ... then 1 else-} 0
172
173 varHdrSizeInWords :: SMRep -> Int{-in words-}
174
175 varHdrSizeInWords sm
176   = case sm of
177     StaticRep _ _          -> 0
178     SpecialisedRep _ _ _ _ -> 0
179     GenericRep _ _ _       -> 0
180     BigTupleRep _          -> 1
181     MuTupleRep _           -> 2 {- (1 + GC_MUT_RESERVED_WORDS) -}
182     DataRep _              -> 1
183     DynamicRep             -> 2
184     BlackHoleRep           -> 0
185     PhantomRep             -> panic "MachMisc.varHdrSizeInWords:phantom"
186 \end{code}
187
188 % - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
189
190 Static closure sizes:
191 \begin{code}
192 charLikeSize, intLikeSize :: Int
193
194 charLikeSize = blahLikeSize CharLikeRep
195 intLikeSize  = blahLikeSize IntLikeRep
196
197 blahLikeSize blah
198   = fromInteger (sizeOf PtrRep)
199   * (fixedHdrSizeInWords + varHdrSizeInWords blahLikeRep + 1)
200   where
201     blahLikeRep = SpecialisedRep blah 0 1 SMNormalForm
202
203 --------
204 mutHS, dataHS, foHS :: StixTree
205
206 mutHS  = blah_hs (MuTupleRep 0)
207 dataHS = blah_hs (DataRep 0)
208
209 {- Semi-hack: to avoid introducing ForeignObjRep,
210    we hard-code the VHS for ForeignObj here.
211 -}
212 foHS   
213   = StInt (toInteger words)
214   where
215     words = fixedHdrSizeInWords + 1{-FOREIGN_VHS-}
216
217 blah_hs blah
218   = StInt (toInteger words)
219   where
220     words = fixedHdrSizeInWords + varHdrSizeInWords blah
221 \end{code}
222
223 % - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
224
225 Size of a @PrimRep@, in bytes.
226
227 \begin{code}
228 sizeOf :: PrimRep -> Integer{-in bytes-}
229     -- the result is an Integer only because it's more convenient
230
231 sizeOf pr = case (primRepToSize pr) of
232   IF_ARCH_alpha({B -> 1; BU -> 1; {-W -> 2; WU -> 2; L -> 4; SF -> 4;-} _ -> 8},)
233   IF_ARCH_sparc({B -> 1; BU -> 1; {-HW -> 2; HWU -> 2;-} W -> 4; {-D -> 8;-} F -> 4; DF -> 8},)
234   IF_ARCH_i386( {B -> 1; {-S -> 2;-} L -> 4; F -> 4; DF -> 8 },)
235 \end{code}
236
237 % - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
238
239 Now the volatile saves and restores.  We add the basic guys to the
240 list of ``user'' registers provided.  Note that there are more basic
241 registers on the restore list, because some are reloaded from
242 constants.
243
244 (@volatileRestores@ used only for wrapper-hungry PrimOps.)
245
246 \begin{code}
247 volatileSaves, volatileRestores :: [MagicId] -> [StixTree]
248
249 save_cands    = [BaseReg,SpA,SuA,SpB,SuB,Hp,HpLim,RetReg]
250 restore_cands = save_cands ++ [StkStubReg,StdUpdRetVecReg]
251
252 volatileSaves vols
253   = map save ((filter callerSaves) (save_cands ++ vols))
254   where
255     save x = StAssign (magicIdPrimRep x) loc reg
256       where
257         reg = StReg (StixMagicId x)
258         loc = case stgReg x of
259                 Save loc -> loc
260                 Always _ -> panic "volatileSaves"
261
262 volatileRestores vols
263   = map restore ((filter callerSaves) (restore_cands ++ vols))
264   where
265     restore x = StAssign (magicIdPrimRep x) reg loc
266       where
267         reg = StReg (StixMagicId x)
268         loc = case stgReg x of
269                 Save loc -> loc
270                 Always _ -> panic "volatileRestores"
271 \end{code}
272
273 % - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
274
275 Obviously slightly weedy
276 (Note that the floating point values aren't terribly important.)
277 ToDo: Fix!(JSM)
278 \begin{code}
279 targetMinDouble = MachDouble (-1.7976931348623157e+308)
280 targetMaxDouble = MachDouble (1.7976931348623157e+308)
281 targetMinInt = mkMachInt (-2147483647)
282 targetMaxInt = mkMachInt 2147483647
283 \end{code}
284
285 % - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
286
287 Storage manager nonsense.  Note that the indices are dependent on
288 the definition of the smInfo structure in SMinterface.lh
289
290 \begin{code}
291 storageMgrInfo, smCAFlist, smOldMutables, smOldLim :: StixTree
292
293 storageMgrInfo   = sStLitLbl SLIT("StorageMgrInfo")
294 smCAFlist        = StInd PtrRep (StIndex PtrRep storageMgrInfo (StInt SM_CAFLIST))
295 smOldMutables    = StInd PtrRep (StIndex PtrRep storageMgrInfo (StInt SM_OLDMUTABLES))
296 smOldLim         = StInd PtrRep (StIndex PtrRep storageMgrInfo (StInt SM_OLDLIM))
297 smStablePtrTable = StInd PtrRep (StIndex PtrRep storageMgrInfo (StInt SM_STABLEPOINTERTABLE))
298 \end{code}
299
300 % - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
301
302 This algorithm for determining the $\log_2$ of exact powers of 2 comes
303 from GCC.  It requires bit manipulation primitives, and we use GHC
304 extensions.  Tough.
305
306 \begin{code}
307 w2i x = word2Int# x
308 i2w x = int2Word# x
309 i2w_s x = (x::Int#)
310
311 exactLog2 :: Integer -> Maybe Integer
312 exactLog2 x
313   = if (x <= 0 || x >= 2147483648) then
314        Nothing
315     else
316        case (fromInteger x) of { I# x# ->
317        if (w2i ((i2w x#) `and#` (i2w (0# -# x#))) /=# x#) then
318           Nothing
319        else
320           Just (toInteger (I# (pow2 x#)))
321        }
322   where
323     shiftr x y = shiftRA# x y
324
325     pow2 x# | x# ==# 1# = 0#
326             | otherwise = 1# +# pow2 (w2i (i2w x# `shiftr` i2w_s 1#))
327 \end{code}
328
329 % - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
330
331 \begin{code}
332 data Cond
333 #if alpha_TARGET_ARCH
334   = ALWAYS      -- For BI (same as BR)
335   | EQQ         -- For CMP and BI (NB: "EQ" is a 1.3 Prelude name)
336   | GE          -- For BI only
337   | GTT         -- For BI only (NB: "GT" is a 1.3 Prelude name)
338   | LE          -- For CMP and BI
339   | LTT         -- For CMP and BI (NB: "LT" is a 1.3 Prelude name)
340   | NE          -- For BI only
341   | NEVER       -- For BI (null instruction)
342   | ULE         -- For CMP only
343   | ULT         -- For CMP only
344 #endif
345 #if i386_TARGET_ARCH
346   = ALWAYS      -- What's really used? ToDo
347   | EQQ
348   | GE
349   | GEU
350   | GTT
351   | GU
352   | LE
353   | LEU
354   | LTT
355   | LU
356   | NE
357   | NEG
358   | POS
359 #endif
360 #if sparc_TARGET_ARCH
361   = ALWAYS      -- What's really used? ToDo
362   | EQQ
363   | GE
364   | GEU
365   | GTT
366   | GU
367   | LE
368   | LEU
369   | LTT
370   | LU
371   | NE
372   | NEG
373   | NEVER
374   | POS
375   | VC
376   | VS
377 #endif
378 \end{code}
379
380 \begin{code}
381 data Size
382 #if alpha_TARGET_ARCH
383     = B     -- byte
384     | BU
385 --  | W     -- word (2 bytes): UNUSED
386 --  | WU    -- : UNUSED
387 --  | L     -- longword (4 bytes): UNUSED
388     | Q     -- quadword (8 bytes)
389 --  | FF    -- VAX F-style floating pt: UNUSED
390 --  | GF    -- VAX G-style floating pt: UNUSED
391 --  | DF    -- VAX D-style floating pt: UNUSED
392 --  | SF    -- IEEE single-precision floating pt: UNUSED
393     | TF    -- IEEE double-precision floating pt
394 #endif
395 #if i386_TARGET_ARCH
396     = B     -- byte (lower)
397 --  | HB    -- higher byte **UNUSED**
398 --  | S     -- : UNUSED
399     | L
400     | F     -- IEEE single-precision floating pt
401     | DF    -- IEEE single-precision floating pt
402 #endif
403 #if sparc_TARGET_ARCH
404     = B     -- byte (signed)
405     | BU    -- byte (unsigned)
406 --  | HW    -- halfword, 2 bytes (signed): UNUSED
407 --  | HWU   -- halfword, 2 bytes (unsigned): UNUSED
408     | W     -- word, 4 bytes
409 --  | D     -- doubleword, 8 bytes: UNUSED
410     | F     -- IEEE single-precision floating pt
411     | DF    -- IEEE single-precision floating pt
412 #endif
413
414 primRepToSize :: PrimRep -> Size
415
416 primRepToSize PtrRep        = IF_ARCH_alpha( Q,  IF_ARCH_i386( L, IF_ARCH_sparc( W ,)))
417 primRepToSize CodePtrRep    = IF_ARCH_alpha( Q,  IF_ARCH_i386( L, IF_ARCH_sparc( W ,)))
418 primRepToSize DataPtrRep    = IF_ARCH_alpha( Q,  IF_ARCH_i386( L, IF_ARCH_sparc( W ,)))
419 primRepToSize RetRep        = IF_ARCH_alpha( Q,  IF_ARCH_i386( L, IF_ARCH_sparc( W ,)))
420 primRepToSize CostCentreRep = IF_ARCH_alpha( Q,  IF_ARCH_i386( L, IF_ARCH_sparc( W ,)))
421 primRepToSize CharRep       = IF_ARCH_alpha( BU, IF_ARCH_i386( L, IF_ARCH_sparc( BU,)))
422 primRepToSize IntRep        = IF_ARCH_alpha( Q,  IF_ARCH_i386( L, IF_ARCH_sparc( W ,)))
423 primRepToSize WordRep       = IF_ARCH_alpha( Q,  IF_ARCH_i386( L, IF_ARCH_sparc( W ,)))
424 primRepToSize AddrRep       = IF_ARCH_alpha( Q,  IF_ARCH_i386( L, IF_ARCH_sparc( W ,)))
425 primRepToSize FloatRep      = IF_ARCH_alpha( TF, IF_ARCH_i386( F, IF_ARCH_sparc( F ,)))
426 primRepToSize DoubleRep     = IF_ARCH_alpha( TF, IF_ARCH_i386( DF,IF_ARCH_sparc( DF,)))
427 primRepToSize ArrayRep      = IF_ARCH_alpha( Q,  IF_ARCH_i386( L, IF_ARCH_sparc( W ,)))
428 primRepToSize ByteArrayRep  = IF_ARCH_alpha( Q,  IF_ARCH_i386( L, IF_ARCH_sparc( W ,)))
429 primRepToSize StablePtrRep  = IF_ARCH_alpha( Q,  IF_ARCH_i386( L, IF_ARCH_sparc( W ,)))
430 primRepToSize ForeignObjRep  = IF_ARCH_alpha( Q,         IF_ARCH_i386( L, IF_ARCH_sparc( W ,)))
431 \end{code}
432
433 %************************************************************************
434 %*                                                                      *
435 \subsection{Machine's assembly language}
436 %*                                                                      *
437 %************************************************************************
438
439 We have a few common ``instructions'' (nearly all the pseudo-ops) but
440 mostly all of @Instr@ is machine-specific.
441
442 \begin{code}
443 data Instr
444   = COMMENT FAST_STRING         -- comment pseudo-op
445   | SEGMENT CodeSegment         -- {data,text} segment pseudo-op
446   | LABEL   CLabel              -- global label pseudo-op
447   | ASCII   Bool                -- True <=> needs backslash conversion
448             String              -- the literal string
449   | DATA    Size
450             [Imm]
451 \end{code}
452
453 \begin{code}
454 #if alpha_TARGET_ARCH
455
456 -- data Instr continues...
457
458 -- Loads and stores.
459
460               | LD            Size Reg MachRegsAddr -- size, dst, src
461               | LDA           Reg MachRegsAddr      -- dst, src
462               | LDAH          Reg MachRegsAddr      -- dst, src
463               | LDGP          Reg MachRegsAddr      -- dst, src
464               | LDI           Size Reg Imm  -- size, dst, src
465               | ST            Size Reg MachRegsAddr -- size, src, dst
466
467 -- Int Arithmetic.
468
469               | CLR           Reg                   -- dst
470               | ABS           Size RI Reg           -- size, src, dst
471               | NEG           Size Bool RI Reg      -- size, overflow, src, dst
472               | ADD           Size Bool Reg RI Reg  -- size, overflow, src, src, dst
473               | SADD          Size Size Reg RI Reg  -- size, scale, src, src, dst
474               | SUB           Size Bool Reg RI Reg  -- size, overflow, src, src, dst
475               | SSUB          Size Size Reg RI Reg  -- size, scale, src, src, dst
476               | MUL           Size Bool Reg RI Reg  -- size, overflow, src, src, dst
477               | DIV           Size Bool Reg RI Reg  -- size, unsigned, src, src, dst
478               | REM           Size Bool Reg RI Reg  -- size, unsigned, src, src, dst
479
480 -- Simple bit-twiddling.
481
482               | NOT           RI Reg
483               | AND           Reg RI Reg
484               | ANDNOT        Reg RI Reg
485               | OR            Reg RI Reg
486               | ORNOT         Reg RI Reg
487               | XOR           Reg RI Reg
488               | XORNOT        Reg RI Reg
489               | SLL           Reg RI Reg
490               | SRL           Reg RI Reg
491               | SRA           Reg RI Reg
492
493               | ZAP           Reg RI Reg
494               | ZAPNOT        Reg RI Reg
495
496               | NOP
497
498 -- Comparison
499
500               | CMP           Cond Reg RI Reg
501
502 -- Float Arithmetic.
503
504               | FCLR          Reg
505               | FABS          Reg Reg
506               | FNEG          Size Reg Reg
507               | FADD          Size Reg Reg Reg
508               | FDIV          Size Reg Reg Reg
509               | FMUL          Size Reg Reg Reg
510               | FSUB          Size Reg Reg Reg
511               | CVTxy         Size Size Reg Reg
512               | FCMP          Size Cond Reg Reg Reg
513               | FMOV          Reg Reg
514
515 -- Jumping around.
516
517               | BI            Cond Reg Imm
518               | BF            Cond Reg Imm
519               | BR            Imm
520               | JMP           Reg MachRegsAddr Int
521               | BSR           Imm Int
522               | JSR           Reg MachRegsAddr Int
523
524 -- Alpha-specific pseudo-ops.
525
526               | FUNBEGIN CLabel
527               | FUNEND CLabel
528
529 data RI
530   = RIReg Reg
531   | RIImm Imm
532
533 #endif {- alpha_TARGET_ARCH -}
534 \end{code}
535
536 \begin{code}
537 #if i386_TARGET_ARCH
538
539 -- data Instr continues...
540
541 -- Moves.
542
543               | MOV           Size Operand Operand
544               | MOVZX         Size Operand Operand -- size is the size of operand 2
545               | MOVSX         Size Operand Operand -- size is the size of operand 2
546
547 -- Load effective address (also a very useful three-operand add instruction :-)
548
549               | LEA           Size Operand Operand
550
551 -- Int Arithmetic.
552
553               | ADD           Size Operand Operand
554               | SUB           Size Operand Operand
555
556 -- Multiplication (signed and unsigned), Division (signed and unsigned),
557 -- result in %eax, %edx.
558
559               | IMUL          Size Operand Operand
560               | IDIV          Size Operand
561
562 -- Simple bit-twiddling.
563
564               | AND           Size Operand Operand
565               | OR            Size Operand Operand
566               | XOR           Size Operand Operand
567               | NOT           Size Operand
568               | NEGI          Size Operand -- NEG instruction (name clash with Cond)
569               | SHL           Size Operand Operand -- 1st operand must be an Imm
570               | SAR           Size Operand Operand -- 1st operand must be an Imm
571               | SHR           Size Operand Operand -- 1st operand must be an Imm
572               | NOP
573
574 -- Float Arithmetic. -- ToDo for 386
575
576 -- Note that we cheat by treating F{ABS,MOV,NEG} of doubles as single instructions
577 -- right up until we spit them out.
578
579               | SAHF          -- stores ah into flags
580               | FABS
581               | FADD          Size Operand -- src
582               | FADDP
583               | FIADD         Size MachRegsAddr -- src
584               | FCHS
585               | FCOM          Size Operand -- src
586               | FCOS
587               | FDIV          Size Operand -- src
588               | FDIVP
589               | FIDIV         Size MachRegsAddr -- src
590               | FDIVR         Size Operand -- src
591               | FDIVRP
592               | FIDIVR        Size MachRegsAddr -- src
593               | FICOM         Size MachRegsAddr -- src
594               | FILD          Size MachRegsAddr Reg -- src, dst
595               | FIST          Size MachRegsAddr -- dst
596               | FLD           Size Operand -- src
597               | FLD1
598               | FLDZ
599               | FMUL          Size Operand -- src
600               | FMULP
601               | FIMUL         Size MachRegsAddr -- src
602               | FRNDINT
603               | FSIN
604               | FSQRT
605               | FST           Size Operand -- dst
606               | FSTP          Size Operand -- dst
607               | FSUB          Size Operand -- src
608               | FSUBP
609               | FISUB         Size MachRegsAddr -- src
610               | FSUBR         Size Operand -- src
611               | FSUBRP
612               | FISUBR        Size MachRegsAddr -- src
613               | FTST
614               | FCOMP         Size Operand -- src
615               | FUCOMPP
616               | FXCH
617               | FNSTSW
618               | FNOP
619
620 -- Comparison
621
622               | TEST          Size Operand Operand
623               | CMP           Size Operand Operand
624               | SETCC         Cond Operand
625
626 -- Stack Operations.
627
628               | PUSH          Size Operand
629               | POP           Size Operand
630
631 -- Jumping around.
632
633               | JMP           Operand -- target
634               | JXX           Cond CLabel -- target
635               | CALL          Imm
636
637 -- Other things.
638
639               | CLTD -- sign extend %eax into %edx:%eax
640
641 data Operand
642   = OpReg  Reg          -- register
643   | OpImm  Imm          -- immediate value
644   | OpAddr MachRegsAddr -- memory reference
645
646 #endif {- i386_TARGET_ARCH -}
647 \end{code}
648
649 \begin{code}
650 #if sparc_TARGET_ARCH
651
652 -- data Instr continues...
653
654 -- Loads and stores.
655
656               | LD            Size MachRegsAddr Reg -- size, src, dst
657               | ST            Size Reg MachRegsAddr -- size, src, dst
658
659 -- Int Arithmetic.
660
661               | ADD           Bool Bool Reg RI Reg -- x?, cc?, src1, src2, dst
662               | SUB           Bool Bool Reg RI Reg -- x?, cc?, src1, src2, dst
663
664 -- Simple bit-twiddling.
665
666               | AND           Bool Reg RI Reg -- cc?, src1, src2, dst
667               | ANDN          Bool Reg RI Reg -- cc?, src1, src2, dst
668               | OR            Bool Reg RI Reg -- cc?, src1, src2, dst
669               | ORN           Bool Reg RI Reg -- cc?, src1, src2, dst
670               | XOR           Bool Reg RI Reg -- cc?, src1, src2, dst
671               | XNOR          Bool Reg RI Reg -- cc?, src1, src2, dst
672               | SLL           Reg RI Reg -- src1, src2, dst
673               | SRL           Reg RI Reg -- src1, src2, dst
674               | SRA           Reg RI Reg -- src1, src2, dst
675               | SETHI         Imm Reg -- src, dst
676               | NOP           -- Really SETHI 0, %g0, but worth an alias
677
678 -- Float Arithmetic.
679
680 -- Note that we cheat by treating F{ABS,MOV,NEG} of doubles as single instructions
681 -- right up until we spit them out.
682
683               | FABS          Size Reg Reg -- src dst
684               | FADD          Size Reg Reg Reg -- src1, src2, dst
685               | FCMP          Bool Size Reg Reg -- exception?, src1, src2, dst
686               | FDIV          Size Reg Reg Reg -- src1, src2, dst
687               | FMOV          Size Reg Reg -- src, dst
688               | FMUL          Size Reg Reg Reg -- src1, src2, dst
689               | FNEG          Size Reg Reg -- src, dst
690               | FSQRT         Size Reg Reg -- src, dst
691               | FSUB          Size Reg Reg Reg -- src1, src2, dst
692               | FxTOy         Size Size Reg Reg -- src, dst
693
694 -- Jumping around.
695
696               | BI            Cond Bool Imm -- cond, annul?, target
697               | BF            Cond Bool Imm -- cond, annul?, target
698
699               | JMP           MachRegsAddr -- target
700               | CALL          Imm Int Bool -- target, args, terminal
701
702 data RI = RIReg Reg
703         | RIImm Imm
704
705 riZero :: RI -> Bool
706
707 riZero (RIImm (ImmInt 0))           = True
708 riZero (RIImm (ImmInteger 0))       = True
709 riZero (RIReg (FixedReg ILIT(0)))   = True
710 riZero _                            = False
711
712 #endif {- sparc_TARGET_ARCH -}
713 \end{code}