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