[project @ 1997-10-19 22:13:38 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(..), Address(..)
59                         )
60
61 import OrdList          ( OrdList )
62 import PrimRep          ( PrimRep(..) )
63 import SMRep            ( SMRep(..), SMSpecRepKind(..), SMUpdateKind(..) )
64 import Stix             ( StixTree(..), StixReg(..), sStLitLbl,
65                           CodeSegment
66                         )
67 import Util             ( panic )
68 \end{code}
69
70 \begin{code}
71 underscorePrefix :: Bool   -- leading underscore on labels?
72
73 underscorePrefix
74   = IF_ARCH_alpha(False
75     ,{-else-} IF_ARCH_i386(
76         IF_OS_linuxaout(True
77         , IF_OS_freebsd(True
78         , IF_OS_cygwin32(True
79         , IF_OS_bsdi(True
80         , {-otherwise-} False)))
81         )
82      ,{-else-}IF_ARCH_sparc(
83         IF_OS_sunos4(True, {-otherwise-} False)
84      ,)))
85
86 ---------------------------
87 fmtAsmLbl :: String -> String  -- for formatting labels
88
89 fmtAsmLbl s
90   =  IF_ARCH_alpha(
91      {- The alpha assembler likes temporary labels to look like $L123
92         instead of L123.  (Don't toss the L, because then Lf28
93         turns into $f28.)
94      -}
95      '$' : s
96      ,{-otherwise-}
97      s
98      )
99
100 ---------------------------
101 cvtLitLit :: String -> String
102
103 --
104 -- Rather than relying on guessing, use FILE_SIZE to compute the
105 -- _iob offsets.
106 --
107 cvtLitLit "stdin"  = IF_ARCH_alpha("_iob+0" {-probably OK...-}
108                     ,IF_ARCH_i386("_IO_stdin_"
109                     ,IF_ARCH_sparc("__iob+0x0"{-probably OK...-}
110                     ,)))
111
112 cvtLitLit "stdout" = IF_ARCH_alpha("_iob+"++show (``FILE_SIZE''::Int)
113                     ,IF_ARCH_i386("_IO_stdout_"
114                     ,IF_ARCH_sparc("__iob+"++show (``FILE_SIZE''::Int)
115                     ,)))
116 cvtLitLit "stderr" = IF_ARCH_alpha("_iob+"++show (2*(``FILE_SIZE''::Int))
117                     ,IF_ARCH_i386("_IO_stderr_"
118                     ,IF_ARCH_sparc("__iob+"++show (2*(``FILE_SIZE''::Int))
119                     ,)))
120 {-
121 cvtLitLit "stdout" = IF_ARCH_alpha("_iob+56"{-dodgy *at best*...-}
122                     ,IF_ARCH_i386("_IO_stdout_"
123                     ,IF_ARCH_sparc("__iob+0x10"{-dodgy *at best*...-}
124                     ,)))
125 cvtLitLit "stderr" = IF_ARCH_alpha("_iob+112"{-dodgy *at best*...-}
126                     ,IF_ARCH_i386("_IO_stderr_"
127                     ,IF_ARCH_sparc("__iob+0x20"{-dodgy *at best*...-}
128                     ,)))
129 -}
130 cvtLitLit s
131   | isHex s   = s
132   | otherwise = error ("Native code generator can't handle ``" ++ s ++ "''")
133   where
134     isHex ('0':'x':xs) = all isHexDigit xs
135     isHex _ = False
136     -- Now, where have I seen this before?
137     isHexDigit c = isDigit c || c >= 'A' && c <= 'F' || c >= 'a' && c <= 'f'
138 \end{code}
139
140 % ----------------------------------------------------------------
141
142 We (allegedly) put the first six C-call arguments in registers;
143 where do we start putting the rest of them?
144 \begin{code}
145 eXTRA_STK_ARGS_HERE :: Int
146 eXTRA_STK_ARGS_HERE
147   = IF_ARCH_alpha(0, IF_ARCH_i386(23{-6x4bytes-}, IF_ARCH_sparc(23,???)))
148 \end{code}
149
150 % ----------------------------------------------------------------
151
152 @fixedHdrSizeInWords@ and @varHdrSizeInWords@: these are not dependent
153 on target architecture.
154 \begin{code}
155 fixedHdrSizeInWords :: Int
156
157 fixedHdrSizeInWords
158   = 1{-info ptr-} + profFHS + parFHS + tickyFHS
159     -- obviously, we aren't taking non-sequential too seriously yet
160   where
161     profFHS  = if opt_SccProfilingOn then 1 else 0
162     parFHS   = {-if PAR or GRAN then 1 else-} 0
163     tickyFHS = {-if ticky ... then 1 else-} 0
164
165 varHdrSizeInWords :: SMRep -> Int{-in words-}
166
167 varHdrSizeInWords sm
168   = case sm of
169     StaticRep _ _          -> 0
170     SpecialisedRep _ _ _ _ -> 0
171     GenericRep _ _ _       -> 0
172     BigTupleRep _          -> 1
173     MuTupleRep _           -> 2 {- (1 + GC_MUT_RESERVED_WORDS) -}
174     DataRep _              -> 1
175     DynamicRep             -> 2
176     BlackHoleRep           -> 0
177     PhantomRep             -> panic "MachMisc.varHdrSizeInWords:phantom"
178 \end{code}
179
180 % - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
181
182 Static closure sizes:
183 \begin{code}
184 charLikeSize, intLikeSize :: Int
185
186 charLikeSize = blahLikeSize CharLikeRep
187 intLikeSize  = blahLikeSize IntLikeRep
188
189 blahLikeSize blah
190   = fromInteger (sizeOf PtrRep)
191   * (fixedHdrSizeInWords + varHdrSizeInWords blahLikeRep + 1)
192   where
193     blahLikeRep = SpecialisedRep blah 0 1 SMNormalForm
194
195 --------
196 mutHS, dataHS, foHS :: StixTree
197
198 mutHS  = blah_hs (MuTupleRep 0)
199 dataHS = blah_hs (DataRep 0)
200
201 {- Semi-hack: to avoid introducing ForeignObjRep,
202    we hard-code the VHS for ForeignObj here.
203 -}
204 foHS   
205   = StInt (toInteger words)
206   where
207     words = fixedHdrSizeInWords + 1{-FOREIGN_VHS-}
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 Address -- size, dst, src
453               | LDA           Reg Address      -- dst, src
454               | LDAH          Reg Address      -- dst, src
455               | LDGP          Reg Address      -- dst, src
456               | LDI           Size Reg Imm     -- size, dst, src
457               | ST            Size Reg Address -- 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 Address Int
513               | BSR           Imm Int
514               | JSR           Reg Address 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 or CL
562               | SAR           Size Operand Operand -- 1st operand must be an Imm or CL
563               | SHR           Size Operand Operand -- 1st operand must be an Imm or CL
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 Address -- src
576               | FCHS
577               | FCOM          Size Operand -- src
578               | FCOS
579               | FDIV          Size Operand -- src
580               | FDIVP
581               | FIDIV         Size Address -- src
582               | FDIVR         Size Operand -- src
583               | FDIVRP
584               | FIDIVR        Size Address -- src
585               | FICOM         Size Address -- src
586               | FILD          Size Address Reg -- src, dst
587               | FIST          Size Address -- dst
588               | FLD           Size Operand -- src
589               | FLD1
590               | FLDZ
591               | FMUL          Size Operand -- src
592               | FMULP
593               | FIMUL         Size Address -- 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 Address -- src
602               | FSUBR         Size Operand -- src
603               | FSUBRP
604               | FISUBR        Size Address -- 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 Address      -- 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 Address Reg -- size, src, dst
649               | ST            Size Reg Address -- 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           Address      -- 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}