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