[project @ 1997-06-05 20:53:33 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,
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 :: StixTree
205
206 mutHS  = blah_hs (MuTupleRep 0)
207 dataHS = blah_hs (DataRep 0)
208
209 blah_hs blah
210   = StInt (toInteger words)
211   where
212     words = fixedHdrSizeInWords + varHdrSizeInWords blah
213 \end{code}
214
215 % - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
216
217 Size of a @PrimRep@, in bytes.
218
219 \begin{code}
220 sizeOf :: PrimRep -> Integer{-in bytes-}
221     -- the result is an Integer only because it's more convenient
222
223 sizeOf pr = case (primRepToSize pr) of
224   IF_ARCH_alpha({B -> 1; BU -> 1; {-W -> 2; WU -> 2; L -> 4; SF -> 4;-} _ -> 8},)
225   IF_ARCH_sparc({B -> 1; BU -> 1; {-HW -> 2; HWU -> 2;-} W -> 4; {-D -> 8;-} F -> 4; DF -> 8},)
226   IF_ARCH_i386( {B -> 1; {-S -> 2;-} L -> 4; F -> 4; DF -> 8 },)
227 \end{code}
228
229 % - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
230
231 Now the volatile saves and restores.  We add the basic guys to the
232 list of ``user'' registers provided.  Note that there are more basic
233 registers on the restore list, because some are reloaded from
234 constants.
235
236 (@volatileRestores@ used only for wrapper-hungry PrimOps.)
237
238 \begin{code}
239 volatileSaves, volatileRestores :: [MagicId] -> [StixTree]
240
241 save_cands    = [BaseReg,SpA,SuA,SpB,SuB,Hp,HpLim,RetReg]
242 restore_cands = save_cands ++ [StkStubReg,StdUpdRetVecReg]
243
244 volatileSaves vols
245   = map save ((filter callerSaves) (save_cands ++ vols))
246   where
247     save x = StAssign (magicIdPrimRep x) loc reg
248       where
249         reg = StReg (StixMagicId x)
250         loc = case stgReg x of
251                 Save loc -> loc
252                 Always _ -> panic "volatileSaves"
253
254 volatileRestores vols
255   = map restore ((filter callerSaves) (restore_cands ++ vols))
256   where
257     restore x = StAssign (magicIdPrimRep x) reg loc
258       where
259         reg = StReg (StixMagicId x)
260         loc = case stgReg x of
261                 Save loc -> loc
262                 Always _ -> panic "volatileRestores"
263 \end{code}
264
265 % - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
266
267 Obviously slightly weedy
268 (Note that the floating point values aren't terribly important.)
269 ToDo: Fix!(JSM)
270 \begin{code}
271 targetMinDouble = MachDouble (-1.7976931348623157e+308)
272 targetMaxDouble = MachDouble (1.7976931348623157e+308)
273 targetMinInt = mkMachInt (-2147483647)
274 targetMaxInt = mkMachInt 2147483647
275 \end{code}
276
277 % - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
278
279 Storage manager nonsense.  Note that the indices are dependent on
280 the definition of the smInfo structure in SMinterface.lh
281
282 \begin{code}
283 storageMgrInfo, smCAFlist, smOldMutables, smOldLim :: StixTree
284
285 storageMgrInfo   = sStLitLbl SLIT("StorageMgrInfo")
286 smCAFlist        = StInd PtrRep (StIndex PtrRep storageMgrInfo (StInt SM_CAFLIST))
287 smOldMutables    = StInd PtrRep (StIndex PtrRep storageMgrInfo (StInt SM_OLDMUTABLES))
288 smOldLim         = StInd PtrRep (StIndex PtrRep storageMgrInfo (StInt SM_OLDLIM))
289 smStablePtrTable = StInd PtrRep (StIndex PtrRep storageMgrInfo (StInt SM_STABLEPOINTERTABLE))
290 \end{code}
291
292 % - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
293
294 This algorithm for determining the $\log_2$ of exact powers of 2 comes
295 from GCC.  It requires bit manipulation primitives, and we use GHC
296 extensions.  Tough.
297
298 \begin{code}
299 w2i x = word2Int# x
300 i2w x = int2Word# x
301 i2w_s x = (x::Int#)
302
303 exactLog2 :: Integer -> Maybe Integer
304 exactLog2 x
305   = if (x <= 0 || x >= 2147483648) then
306        Nothing
307     else
308        case (fromInteger x) of { I# x# ->
309        if (w2i ((i2w x#) `and#` (i2w (0# -# x#))) /=# x#) then
310           Nothing
311        else
312           Just (toInteger (I# (pow2 x#)))
313        }
314   where
315     shiftr x y = shiftRA# x y
316
317     pow2 x# | x# ==# 1# = 0#
318             | otherwise = 1# +# pow2 (w2i (i2w x# `shiftr` i2w_s 1#))
319 \end{code}
320
321 % - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
322
323 \begin{code}
324 data Cond
325 #if alpha_TARGET_ARCH
326   = ALWAYS      -- For BI (same as BR)
327   | EQQ         -- For CMP and BI (NB: "EQ" is a 1.3 Prelude name)
328   | GE          -- For BI only
329   | GTT         -- For BI only (NB: "GT" is a 1.3 Prelude name)
330   | LE          -- For CMP and BI
331   | LTT         -- For CMP and BI (NB: "LT" is a 1.3 Prelude name)
332   | NE          -- For BI only
333   | NEVER       -- For BI (null instruction)
334   | ULE         -- For CMP only
335   | ULT         -- For CMP only
336 #endif
337 #if i386_TARGET_ARCH
338   = ALWAYS      -- What's really used? ToDo
339   | EQQ
340   | GE
341   | GEU
342   | GTT
343   | GU
344   | LE
345   | LEU
346   | LTT
347   | LU
348   | NE
349   | NEG
350   | POS
351 #endif
352 #if sparc_TARGET_ARCH
353   = ALWAYS      -- What's really used? ToDo
354   | EQQ
355   | GE
356   | GEU
357   | GTT
358   | GU
359   | LE
360   | LEU
361   | LTT
362   | LU
363   | NE
364   | NEG
365   | NEVER
366   | POS
367   | VC
368   | VS
369 #endif
370 \end{code}
371
372 \begin{code}
373 data Size
374 #if alpha_TARGET_ARCH
375     = B     -- byte
376     | BU
377 --  | W     -- word (2 bytes): UNUSED
378 --  | WU    -- : UNUSED
379 --  | L     -- longword (4 bytes): UNUSED
380     | Q     -- quadword (8 bytes)
381 --  | FF    -- VAX F-style floating pt: UNUSED
382 --  | GF    -- VAX G-style floating pt: UNUSED
383 --  | DF    -- VAX D-style floating pt: UNUSED
384 --  | SF    -- IEEE single-precision floating pt: UNUSED
385     | TF    -- IEEE double-precision floating pt
386 #endif
387 #if i386_TARGET_ARCH
388     = B     -- byte (lower)
389 --  | HB    -- higher byte **UNUSED**
390 --  | S     -- : UNUSED
391     | L
392     | F     -- IEEE single-precision floating pt
393     | DF    -- IEEE single-precision floating pt
394 #endif
395 #if sparc_TARGET_ARCH
396     = B     -- byte (signed)
397     | BU    -- byte (unsigned)
398 --  | HW    -- halfword, 2 bytes (signed): UNUSED
399 --  | HWU   -- halfword, 2 bytes (unsigned): UNUSED
400     | W     -- word, 4 bytes
401 --  | D     -- doubleword, 8 bytes: UNUSED
402     | F     -- IEEE single-precision floating pt
403     | DF    -- IEEE single-precision floating pt
404 #endif
405
406 primRepToSize :: PrimRep -> Size
407
408 primRepToSize PtrRep        = IF_ARCH_alpha( Q,  IF_ARCH_i386( L, IF_ARCH_sparc( W ,)))
409 primRepToSize CodePtrRep    = IF_ARCH_alpha( Q,  IF_ARCH_i386( L, IF_ARCH_sparc( W ,)))
410 primRepToSize DataPtrRep    = IF_ARCH_alpha( Q,  IF_ARCH_i386( L, IF_ARCH_sparc( W ,)))
411 primRepToSize RetRep        = IF_ARCH_alpha( Q,  IF_ARCH_i386( L, IF_ARCH_sparc( W ,)))
412 primRepToSize CostCentreRep = IF_ARCH_alpha( Q,  IF_ARCH_i386( L, IF_ARCH_sparc( W ,)))
413 primRepToSize CharRep       = IF_ARCH_alpha( BU, IF_ARCH_i386( L, IF_ARCH_sparc( BU,)))
414 primRepToSize IntRep        = IF_ARCH_alpha( Q,  IF_ARCH_i386( L, IF_ARCH_sparc( W ,)))
415 primRepToSize WordRep       = IF_ARCH_alpha( Q,  IF_ARCH_i386( L, IF_ARCH_sparc( W ,)))
416 primRepToSize AddrRep       = IF_ARCH_alpha( Q,  IF_ARCH_i386( L, IF_ARCH_sparc( W ,)))
417 primRepToSize FloatRep      = IF_ARCH_alpha( TF, IF_ARCH_i386( F, IF_ARCH_sparc( F ,)))
418 primRepToSize DoubleRep     = IF_ARCH_alpha( TF, IF_ARCH_i386( DF,IF_ARCH_sparc( DF,)))
419 primRepToSize ArrayRep      = IF_ARCH_alpha( Q,  IF_ARCH_i386( L, IF_ARCH_sparc( W ,)))
420 primRepToSize ByteArrayRep  = IF_ARCH_alpha( Q,  IF_ARCH_i386( L, IF_ARCH_sparc( W ,)))
421 primRepToSize StablePtrRep  = IF_ARCH_alpha( Q,  IF_ARCH_i386( L, IF_ARCH_sparc( W ,)))
422 primRepToSize ForeignObjRep  = IF_ARCH_alpha( Q,         IF_ARCH_i386( L, IF_ARCH_sparc( W ,)))
423 \end{code}
424
425 %************************************************************************
426 %*                                                                      *
427 \subsection{Machine's assembly language}
428 %*                                                                      *
429 %************************************************************************
430
431 We have a few common ``instructions'' (nearly all the pseudo-ops) but
432 mostly all of @Instr@ is machine-specific.
433
434 \begin{code}
435 data Instr
436   = COMMENT FAST_STRING         -- comment pseudo-op
437   | SEGMENT CodeSegment         -- {data,text} segment pseudo-op
438   | LABEL   CLabel              -- global label pseudo-op
439   | ASCII   Bool                -- True <=> needs backslash conversion
440             String              -- the literal string
441   | DATA    Size
442             [Imm]
443 \end{code}
444
445 \begin{code}
446 #if alpha_TARGET_ARCH
447
448 -- data Instr continues...
449
450 -- Loads and stores.
451
452               | LD            Size Reg MachRegsAddr -- size, dst, src
453               | LDA           Reg MachRegsAddr      -- dst, src
454               | LDAH          Reg MachRegsAddr      -- dst, src
455               | LDGP          Reg MachRegsAddr      -- dst, src
456               | LDI           Size Reg Imm  -- size, dst, src
457               | ST            Size Reg MachRegsAddr -- size, src, dst
458
459 -- Int Arithmetic.
460
461               | CLR           Reg                   -- dst
462               | ABS           Size RI Reg           -- size, src, dst
463               | NEG           Size Bool RI Reg      -- size, overflow, src, dst
464               | ADD           Size Bool Reg RI Reg  -- size, overflow, src, src, dst
465               | SADD          Size Size Reg RI Reg  -- size, scale, src, src, dst
466               | SUB           Size Bool Reg RI Reg  -- size, overflow, src, src, dst
467               | SSUB          Size Size Reg RI Reg  -- size, scale, src, src, dst
468               | MUL           Size Bool Reg RI Reg  -- size, overflow, src, src, dst
469               | DIV           Size Bool Reg RI Reg  -- size, unsigned, src, src, dst
470               | REM           Size Bool Reg RI Reg  -- size, unsigned, src, src, dst
471
472 -- Simple bit-twiddling.
473
474               | NOT           RI Reg
475               | AND           Reg RI Reg
476               | ANDNOT        Reg RI Reg
477               | OR            Reg RI Reg
478               | ORNOT         Reg RI Reg
479               | XOR           Reg RI Reg
480               | XORNOT        Reg RI Reg
481               | SLL           Reg RI Reg
482               | SRL           Reg RI Reg
483               | SRA           Reg RI Reg
484
485               | ZAP           Reg RI Reg
486               | ZAPNOT        Reg RI Reg
487
488               | NOP
489
490 -- Comparison
491
492               | CMP           Cond Reg RI Reg
493
494 -- Float Arithmetic.
495
496               | FCLR          Reg
497               | FABS          Reg Reg
498               | FNEG          Size Reg Reg
499               | FADD          Size Reg Reg Reg
500               | FDIV          Size Reg Reg Reg
501               | FMUL          Size Reg Reg Reg
502               | FSUB          Size Reg Reg Reg
503               | CVTxy         Size Size Reg Reg
504               | FCMP          Size Cond Reg Reg Reg
505               | FMOV          Reg Reg
506
507 -- Jumping around.
508
509               | BI            Cond Reg Imm
510               | BF            Cond Reg Imm
511               | BR            Imm
512               | JMP           Reg MachRegsAddr Int
513               | BSR           Imm Int
514               | JSR           Reg MachRegsAddr Int
515
516 -- Alpha-specific pseudo-ops.
517
518               | FUNBEGIN CLabel
519               | FUNEND CLabel
520
521 data RI
522   = RIReg Reg
523   | RIImm Imm
524
525 #endif {- alpha_TARGET_ARCH -}
526 \end{code}
527
528 \begin{code}
529 #if i386_TARGET_ARCH
530
531 -- data Instr continues...
532
533 -- Moves.
534
535               | MOV           Size Operand Operand
536               | MOVZX         Size Operand Operand -- size is the size of operand 2
537               | MOVSX         Size Operand Operand -- size is the size of operand 2
538
539 -- Load effective address (also a very useful three-operand add instruction :-)
540
541               | LEA           Size Operand Operand
542
543 -- Int Arithmetic.
544
545               | ADD           Size Operand Operand
546               | SUB           Size Operand Operand
547
548 -- Multiplication (signed and unsigned), Division (signed and unsigned),
549 -- result in %eax, %edx.
550
551               | IMUL          Size Operand Operand
552               | IDIV          Size Operand
553
554 -- Simple bit-twiddling.
555
556               | AND           Size Operand Operand
557               | OR            Size Operand Operand
558               | XOR           Size Operand Operand
559               | NOT           Size Operand
560               | NEGI          Size Operand -- NEG instruction (name clash with Cond)
561               | SHL           Size Operand Operand -- 1st operand must be an Imm
562               | SAR           Size Operand Operand -- 1st operand must be an Imm
563               | SHR           Size Operand Operand -- 1st operand must be an Imm
564               | NOP
565
566 -- Float Arithmetic. -- ToDo for 386
567
568 -- Note that we cheat by treating F{ABS,MOV,NEG} of doubles as single instructions
569 -- right up until we spit them out.
570
571               | SAHF          -- stores ah into flags
572               | FABS
573               | FADD          Size Operand -- src
574               | FADDP
575               | FIADD         Size MachRegsAddr -- src
576               | FCHS
577               | FCOM          Size Operand -- src
578               | FCOS
579               | FDIV          Size Operand -- src
580               | FDIVP
581               | FIDIV         Size MachRegsAddr -- src
582               | FDIVR         Size Operand -- src
583               | FDIVRP
584               | FIDIVR        Size MachRegsAddr -- src
585               | FICOM         Size MachRegsAddr -- src
586               | FILD          Size MachRegsAddr Reg -- src, dst
587               | FIST          Size MachRegsAddr -- dst
588               | FLD           Size Operand -- src
589               | FLD1
590               | FLDZ
591               | FMUL          Size Operand -- src
592               | FMULP
593               | FIMUL         Size MachRegsAddr -- src
594               | FRNDINT
595               | FSIN
596               | FSQRT
597               | FST           Size Operand -- dst
598               | FSTP          Size Operand -- dst
599               | FSUB          Size Operand -- src
600               | FSUBP
601               | FISUB         Size MachRegsAddr -- src
602               | FSUBR         Size Operand -- src
603               | FSUBRP
604               | FISUBR        Size MachRegsAddr -- src
605               | FTST
606               | FCOMP         Size Operand -- src
607               | FUCOMPP
608               | FXCH
609               | FNSTSW
610               | FNOP
611
612 -- Comparison
613
614               | TEST          Size Operand Operand
615               | CMP           Size Operand Operand
616               | SETCC         Cond Operand
617
618 -- Stack Operations.
619
620               | PUSH          Size Operand
621               | POP           Size Operand
622
623 -- Jumping around.
624
625               | JMP           Operand -- target
626               | JXX           Cond CLabel -- target
627               | CALL          Imm
628
629 -- Other things.
630
631               | CLTD -- sign extend %eax into %edx:%eax
632
633 data Operand
634   = OpReg  Reg          -- register
635   | OpImm  Imm          -- immediate value
636   | OpAddr MachRegsAddr -- memory reference
637
638 #endif {- i386_TARGET_ARCH -}
639 \end{code}
640
641 \begin{code}
642 #if sparc_TARGET_ARCH
643
644 -- data Instr continues...
645
646 -- Loads and stores.
647
648               | LD            Size MachRegsAddr Reg -- size, src, dst
649               | ST            Size Reg MachRegsAddr -- size, src, dst
650
651 -- Int Arithmetic.
652
653               | ADD           Bool Bool Reg RI Reg -- x?, cc?, src1, src2, dst
654               | SUB           Bool Bool Reg RI Reg -- x?, cc?, src1, src2, dst
655
656 -- Simple bit-twiddling.
657
658               | AND           Bool Reg RI Reg -- cc?, src1, src2, dst
659               | ANDN          Bool Reg RI Reg -- cc?, src1, src2, dst
660               | OR            Bool Reg RI Reg -- cc?, src1, src2, dst
661               | ORN           Bool Reg RI Reg -- cc?, src1, src2, dst
662               | XOR           Bool Reg RI Reg -- cc?, src1, src2, dst
663               | XNOR          Bool Reg RI Reg -- cc?, src1, src2, dst
664               | SLL           Reg RI Reg -- src1, src2, dst
665               | SRL           Reg RI Reg -- src1, src2, dst
666               | SRA           Reg RI Reg -- src1, src2, dst
667               | SETHI         Imm Reg -- src, dst
668               | NOP           -- Really SETHI 0, %g0, but worth an alias
669
670 -- Float Arithmetic.
671
672 -- Note that we cheat by treating F{ABS,MOV,NEG} of doubles as single instructions
673 -- right up until we spit them out.
674
675               | FABS          Size Reg Reg -- src dst
676               | FADD          Size Reg Reg Reg -- src1, src2, dst
677               | FCMP          Bool Size Reg Reg -- exception?, src1, src2, dst
678               | FDIV          Size Reg Reg Reg -- src1, src2, dst
679               | FMOV          Size Reg Reg -- src, dst
680               | FMUL          Size Reg Reg Reg -- src1, src2, dst
681               | FNEG          Size Reg Reg -- src, dst
682               | FSQRT         Size Reg Reg -- src, dst
683               | FSUB          Size Reg Reg Reg -- src1, src2, dst
684               | FxTOy         Size Size Reg Reg -- src, dst
685
686 -- Jumping around.
687
688               | BI            Cond Bool Imm -- cond, annul?, target
689               | BF            Cond Bool Imm -- cond, annul?, target
690
691               | JMP           MachRegsAddr -- target
692               | CALL          Imm Int Bool -- target, args, terminal
693
694 data RI = RIReg Reg
695         | RIImm Imm
696
697 riZero :: RI -> Bool
698
699 riZero (RIImm (ImmInt 0))           = True
700 riZero (RIImm (ImmInteger 0))       = True
701 riZero (RIReg (FixedReg ILIT(0)))   = True
702 riZero _                            = False
703
704 #endif {- sparc_TARGET_ARCH -}
705 \end{code}