PprMach.hs 70.3 KB
Newer Older
1
2
3
4
5
6
7
{-# OPTIONS -w #-}
-- The above warning supression flag is a temporary kludge.
-- While working on this module you are encouraged to remove it and fix
-- any warnings in the module. See
--     http://hackage.haskell.org/trac/ghc/wiki/Commentary/CodingStyle#Warnings
-- for details

8
9
10
11
-----------------------------------------------------------------------------
--
-- Pretty-printing assembly language
--
12
13
-- (c) The University of Glasgow 1993-2005
--
14
-----------------------------------------------------------------------------
15

16
17
18
-- We start with the @pprXXX@s with some cross-platform commonality
-- (e.g., 'pprReg'); we conclude with the no-commonality monster,
-- 'pprInstr'.
19
20
21

#include "nativeGen/NCG.h"

22
module PprMach ( 
23
24
	pprNatCmmTop, pprBasicBlock, pprSectionHeader, pprData,
	pprInstr, pprSize, pprUserReg
25
26
  ) where

27

28
#include "HsVersions.h"
29

30
import Cmm
31
import MachOp		( MachRep(..), wordRep, isFloatingRep )
32
import MachRegs		-- may differ per-platform
33
34
35
36
import MachInstrs

import CLabel		( CLabel, pprCLabel, externallyVisibleCLabel,
			  labelDynamic, mkAsmTempLabel, entryLblToInfoLbl )
37
38
39
#if HAVE_SUBSECTIONS_VIA_SYMBOLS
import CLabel       ( mkDeadStripPreventer )
#endif
40

41
import Panic		( panic )
42
import Unique		( pprUnique )
43
import Pretty
44
import FastString
45
import qualified Outputable
46
import Outputable	( Outputable )
47

48
import Data.Array.ST
49
import Data.Word	( Word8 )
Simon Marlow's avatar
Simon Marlow committed
50
51
52
import Control.Monad.ST
import Data.Char	( chr, ord )
import Data.Maybe       ( isJust )
53

54
#if powerpc_TARGET_ARCH || darwin_TARGET_OS
Simon Marlow's avatar
Simon Marlow committed
55
56
import Data.Word(Word32)
import Data.Bits
57
58
59
60
#endif

-- -----------------------------------------------------------------------------
-- Printing this stuff out
61
62
63
64

asmSDoc d = Outputable.withPprStyleDoc (
	      Outputable.mkCodeStyle Outputable.AsmStyle) d
pprCLabel_asm l = asmSDoc (pprCLabel l)
65

66
67
68
69
70
pprNatCmmTop :: NatCmmTop -> Doc
pprNatCmmTop (CmmData section dats) = 
  pprSectionHeader section $$ vcat (map pprData dats)

 -- special case for split markers:
71
pprNatCmmTop (CmmProc [] lbl _ (ListGraph [])) = pprLabel lbl
72

73
pprNatCmmTop (CmmProc info lbl params (ListGraph blocks)) = 
74
  pprSectionHeader Text $$
75
76
77
  (if null info then -- blocks guaranteed not null, so label needed
       pprLabel lbl
   else
78
79
80
81
#if HAVE_SUBSECTIONS_VIA_SYMBOLS
            pprCLabel_asm (mkDeadStripPreventer $ entryLblToInfoLbl lbl)
                <> char ':' $$
#endif
82
83
84
85
86
87
       vcat (map pprData info) $$
       pprLabel (entryLblToInfoLbl lbl)
  ) $$
  vcat (map pprBasicBlock blocks)
     -- ^ Even the first block gets a label, because with branch-chain
     -- elimination, it might be the target of a goto.
88
89
90
91
92
93
94
95
96
97
98
99
100
101
#if HAVE_SUBSECTIONS_VIA_SYMBOLS
        -- If we are using the .subsections_via_symbols directive
        -- (available on recent versions of Darwin),
        -- we have to make sure that there is some kind of reference
        -- from the entry code to a label on the _top_ of of the info table,
        -- so that the linker will not think it is unreferenced and dead-strip
        -- it. That's why the label is called a DeadStripPreventer (_dsp).
  $$ if not (null info)
		    then text "\t.long "
		      <+> pprCLabel_asm (entryLblToInfoLbl lbl)
		      <+> char '-'
		      <+> pprCLabel_asm (mkDeadStripPreventer $ entryLblToInfoLbl lbl)
		    else empty
#endif
102
103
104
105
106
107
108
109
110
111
112
113


pprBasicBlock :: NatBasicBlock -> Doc
pprBasicBlock (BasicBlock (BlockId id) instrs) =
  pprLabel (mkAsmTempLabel id) $$
  vcat (map pprInstr instrs)

-- -----------------------------------------------------------------------------
-- pprReg: print a 'Reg'

-- For x86, the way we print a register name depends
-- on which bit of it we care about.  Yurgh.
114

115
pprUserReg :: Reg -> Doc
116
pprUserReg = pprReg IF_ARCH_i386(I32,) IF_ARCH_x86_64(I64,)
117

118
pprReg :: IF_ARCH_i386(MachRep ->,) IF_ARCH_x86_64(MachRep ->,) Reg -> Doc
119

120
pprReg IF_ARCH_i386(s,) IF_ARCH_x86_64(s,) r
121
  = case r of
122
      RealReg i      -> ppr_reg_no IF_ARCH_i386(s,) IF_ARCH_x86_64(s,) i
123
124
125
126
      VirtualRegI  u  -> text "%vI_" <> asmSDoc (pprUnique u)
      VirtualRegHi u  -> text "%vHi_" <> asmSDoc (pprUnique u)
      VirtualRegF  u  -> text "%vF_" <> asmSDoc (pprUnique u)
      VirtualRegD  u  -> text "%vD_" <> asmSDoc (pprUnique u)
127
128
  where
#if alpha_TARGET_ARCH
129
    ppr_reg_no :: Int -> Doc
sof's avatar
sof committed
130
    ppr_reg_no i = ptext
131
      (case i of {
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
	 0 -> SLIT("$0");    1 -> SLIT("$1");
	 2 -> SLIT("$2");    3 -> SLIT("$3");
	 4 -> SLIT("$4");    5 -> SLIT("$5");
	 6 -> SLIT("$6");    7 -> SLIT("$7");
	 8 -> SLIT("$8");    9 -> SLIT("$9");
	10 -> SLIT("$10");  11 -> SLIT("$11");
	12 -> SLIT("$12");  13 -> SLIT("$13");
	14 -> SLIT("$14");  15 -> SLIT("$15");
	16 -> SLIT("$16");  17 -> SLIT("$17");
	18 -> SLIT("$18");  19 -> SLIT("$19");
	20 -> SLIT("$20");  21 -> SLIT("$21");
	22 -> SLIT("$22");  23 -> SLIT("$23");
	24 -> SLIT("$24");  25 -> SLIT("$25");
	26 -> SLIT("$26");  27 -> SLIT("$27");
	28 -> SLIT("$28");  29 -> SLIT("$29");
	30 -> SLIT("$30");  31 -> SLIT("$31");
	32 -> SLIT("$f0");  33 -> SLIT("$f1");
	34 -> SLIT("$f2");  35 -> SLIT("$f3");
	36 -> SLIT("$f4");  37 -> SLIT("$f5");
	38 -> SLIT("$f6");  39 -> SLIT("$f7");
	40 -> SLIT("$f8");  41 -> SLIT("$f9");
	42 -> SLIT("$f10"); 43 -> SLIT("$f11");
	44 -> SLIT("$f12"); 45 -> SLIT("$f13");
	46 -> SLIT("$f14"); 47 -> SLIT("$f15");
	48 -> SLIT("$f16"); 49 -> SLIT("$f17");
	50 -> SLIT("$f18"); 51 -> SLIT("$f19");
	52 -> SLIT("$f20"); 53 -> SLIT("$f21");
	54 -> SLIT("$f22"); 55 -> SLIT("$f23");
	56 -> SLIT("$f24"); 57 -> SLIT("$f25");
	58 -> SLIT("$f26"); 59 -> SLIT("$f27");
	60 -> SLIT("$f28"); 61 -> SLIT("$f29");
	62 -> SLIT("$f30"); 63 -> SLIT("$f31");
	_  -> SLIT("very naughty alpha register")
165
166
167
      })
#endif
#if i386_TARGET_ARCH
168
169
170
171
    ppr_reg_no :: MachRep -> Int -> Doc
    ppr_reg_no I8   = ppr_reg_byte
    ppr_reg_no I16  = ppr_reg_word
    ppr_reg_no _    = ppr_reg_long
172
173

    ppr_reg_byte i = ptext
174
      (case i of {
175
176
	 0 -> SLIT("%al");     1 -> SLIT("%bl");
	 2 -> SLIT("%cl");     3 -> SLIT("%dl");
177
	_  -> SLIT("very naughty I386 byte register")
178
179
      })

180
    ppr_reg_word i = ptext
181
      (case i of {
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
	 0 -> SLIT("%ax");     1 -> SLIT("%bx");
	 2 -> SLIT("%cx");     3 -> SLIT("%dx");
	 4 -> SLIT("%si");     5 -> SLIT("%di");
	 6 -> SLIT("%bp");     7 -> SLIT("%sp");
	_  -> SLIT("very naughty I386 word register")
      })

    ppr_reg_long i = ptext
      (case i of {
	 0 -> SLIT("%eax");    1 -> SLIT("%ebx");
	 2 -> SLIT("%ecx");    3 -> SLIT("%edx");
	 4 -> SLIT("%esi");    5 -> SLIT("%edi");
	 6 -> SLIT("%ebp");    7 -> SLIT("%esp");
	 8 -> SLIT("%fake0");  9 -> SLIT("%fake1");
	10 -> SLIT("%fake2"); 11 -> SLIT("%fake3");
	12 -> SLIT("%fake4"); 13 -> SLIT("%fake5");
198
	_  -> SLIT("very naughty I386 register")
199
200
      })
#endif
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263

#if x86_64_TARGET_ARCH
    ppr_reg_no :: MachRep -> Int -> Doc
    ppr_reg_no I8   = ppr_reg_byte
    ppr_reg_no I16  = ppr_reg_word
    ppr_reg_no I32  = ppr_reg_long
    ppr_reg_no _    = ppr_reg_quad

    ppr_reg_byte i = ptext
      (case i of {
	 0 -> SLIT("%al");     1 -> SLIT("%bl");
	 2 -> SLIT("%cl");     3 -> SLIT("%dl");
	 4 -> SLIT("%sil");    5 -> SLIT("%dil"); -- new 8-bit regs!
	 6 -> SLIT("%bpl");    7 -> SLIT("%spl");
	 8 -> SLIT("%r8b");    9  -> SLIT("%r9b");
	10 -> SLIT("%r10b");   11 -> SLIT("%r11b");
	12 -> SLIT("%r12b");   13 -> SLIT("%r13b");
	14 -> SLIT("%r14b");   15 -> SLIT("%r15b");
	_  -> SLIT("very naughty x86_64 byte register")
      })

    ppr_reg_word i = ptext
      (case i of {
	 0 -> SLIT("%ax");     1 -> SLIT("%bx");
	 2 -> SLIT("%cx");     3 -> SLIT("%dx");
	 4 -> SLIT("%si");     5 -> SLIT("%di");
	 6 -> SLIT("%bp");     7 -> SLIT("%sp");
	 8 -> SLIT("%r8w");    9  -> SLIT("%r9w");
	10 -> SLIT("%r10w");   11 -> SLIT("%r11w");
	12 -> SLIT("%r12w");   13 -> SLIT("%r13w");
	14 -> SLIT("%r14w");   15 -> SLIT("%r15w");
	_  -> SLIT("very naughty x86_64 word register")
      })

    ppr_reg_long i = ptext
      (case i of {
	 0 -> SLIT("%eax");    1  -> SLIT("%ebx");
	 2 -> SLIT("%ecx");    3  -> SLIT("%edx");
	 4 -> SLIT("%esi");    5  -> SLIT("%edi");
	 6 -> SLIT("%ebp");    7  -> SLIT("%esp");
	 8 -> SLIT("%r8d");    9  -> SLIT("%r9d");
	10 -> SLIT("%r10d");   11 -> SLIT("%r11d");
	12 -> SLIT("%r12d");   13 -> SLIT("%r13d");
	14 -> SLIT("%r14d");   15 -> SLIT("%r15d");
	_  -> SLIT("very naughty x86_64 register")
      })

    ppr_reg_quad i = ptext
      (case i of {
	 0 -> SLIT("%rax");	1 -> SLIT("%rbx");
	 2 -> SLIT("%rcx");	3 -> SLIT("%rdx");
	 4 -> SLIT("%rsi");	5 -> SLIT("%rdi");
	 6 -> SLIT("%rbp");	7 -> SLIT("%rsp");
	 8 -> SLIT("%r8");  	9 -> SLIT("%r9");
	10 -> SLIT("%r10");    11 -> SLIT("%r11");
	12 -> SLIT("%r12");    13 -> SLIT("%r13");
	14 -> SLIT("%r14");    15 -> SLIT("%r15");
	16 -> SLIT("%xmm0");   17 -> SLIT("%xmm1");
	18 -> SLIT("%xmm2");   19 -> SLIT("%xmm3");
	20 -> SLIT("%xmm4");   21 -> SLIT("%xmm5");
	22 -> SLIT("%xmm6");   23 -> SLIT("%xmm7");
	24 -> SLIT("%xmm8");   25 -> SLIT("%xmm9");
	26 -> SLIT("%xmm10");  27 -> SLIT("%xmm11");
264
265
266
	28 -> SLIT("%xmm12");  29 -> SLIT("%xmm13");
	30 -> SLIT("%xmm14");  31 -> SLIT("%xmm15");
	_  -> SLIT("very naughty x86_64 register")
267
268
269
      })
#endif

270
#if sparc_TARGET_ARCH
271
    ppr_reg_no :: Int -> Doc
sof's avatar
sof committed
272
    ppr_reg_no i = ptext
273
      (case i of {
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
	 0 -> SLIT("%g0");   1 -> SLIT("%g1");
	 2 -> SLIT("%g2");   3 -> SLIT("%g3");
	 4 -> SLIT("%g4");   5 -> SLIT("%g5");
	 6 -> SLIT("%g6");   7 -> SLIT("%g7");
	 8 -> SLIT("%o0");   9 -> SLIT("%o1");
	10 -> SLIT("%o2");  11 -> SLIT("%o3");
	12 -> SLIT("%o4");  13 -> SLIT("%o5");
	14 -> SLIT("%o6");  15 -> SLIT("%o7");
	16 -> SLIT("%l0");  17 -> SLIT("%l1");
	18 -> SLIT("%l2");  19 -> SLIT("%l3");
	20 -> SLIT("%l4");  21 -> SLIT("%l5");
	22 -> SLIT("%l6");  23 -> SLIT("%l7");
	24 -> SLIT("%i0");  25 -> SLIT("%i1");
	26 -> SLIT("%i2");  27 -> SLIT("%i3");
	28 -> SLIT("%i4");  29 -> SLIT("%i5");
	30 -> SLIT("%i6");  31 -> SLIT("%i7");
	32 -> SLIT("%f0");  33 -> SLIT("%f1");
	34 -> SLIT("%f2");  35 -> SLIT("%f3");
	36 -> SLIT("%f4");  37 -> SLIT("%f5");
	38 -> SLIT("%f6");  39 -> SLIT("%f7");
	40 -> SLIT("%f8");  41 -> SLIT("%f9");
	42 -> SLIT("%f10"); 43 -> SLIT("%f11");
	44 -> SLIT("%f12"); 45 -> SLIT("%f13");
	46 -> SLIT("%f14"); 47 -> SLIT("%f15");
	48 -> SLIT("%f16"); 49 -> SLIT("%f17");
	50 -> SLIT("%f18"); 51 -> SLIT("%f19");
	52 -> SLIT("%f20"); 53 -> SLIT("%f21");
	54 -> SLIT("%f22"); 55 -> SLIT("%f23");
	56 -> SLIT("%f24"); 57 -> SLIT("%f25");
	58 -> SLIT("%f26"); 59 -> SLIT("%f27");
	60 -> SLIT("%f28"); 61 -> SLIT("%f29");
	62 -> SLIT("%f30"); 63 -> SLIT("%f31");
	_  -> SLIT("very naughty sparc register")
307
308
      })
#endif
309
#if powerpc_TARGET_ARCH
310
#if darwin_TARGET_OS
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
    ppr_reg_no :: Int -> Doc
    ppr_reg_no i = ptext
      (case i of {
	 0 -> SLIT("r0");   1 -> SLIT("r1");
	 2 -> SLIT("r2");   3 -> SLIT("r3");
	 4 -> SLIT("r4");   5 -> SLIT("r5");
	 6 -> SLIT("r6");   7 -> SLIT("r7");
	 8 -> SLIT("r8");   9 -> SLIT("r9");
	10 -> SLIT("r10");  11 -> SLIT("r11");
	12 -> SLIT("r12");  13 -> SLIT("r13");
	14 -> SLIT("r14");  15 -> SLIT("r15");
	16 -> SLIT("r16");  17 -> SLIT("r17");
	18 -> SLIT("r18");  19 -> SLIT("r19");
	20 -> SLIT("r20");  21 -> SLIT("r21");
	22 -> SLIT("r22");  23 -> SLIT("r23");
	24 -> SLIT("r24");  25 -> SLIT("r25");
	26 -> SLIT("r26");  27 -> SLIT("r27");
	28 -> SLIT("r28");  29 -> SLIT("r29");
	30 -> SLIT("r30");  31 -> SLIT("r31");
	32 -> SLIT("f0");  33 -> SLIT("f1");
	34 -> SLIT("f2");  35 -> SLIT("f3");
	36 -> SLIT("f4");  37 -> SLIT("f5");
	38 -> SLIT("f6");  39 -> SLIT("f7");
	40 -> SLIT("f8");  41 -> SLIT("f9");
	42 -> SLIT("f10"); 43 -> SLIT("f11");
	44 -> SLIT("f12"); 45 -> SLIT("f13");
	46 -> SLIT("f14"); 47 -> SLIT("f15");
	48 -> SLIT("f16"); 49 -> SLIT("f17");
	50 -> SLIT("f18"); 51 -> SLIT("f19");
	52 -> SLIT("f20"); 53 -> SLIT("f21");
	54 -> SLIT("f22"); 55 -> SLIT("f23");
	56 -> SLIT("f24"); 57 -> SLIT("f25");
	58 -> SLIT("f26"); 59 -> SLIT("f27");
	60 -> SLIT("f28"); 61 -> SLIT("f29");
	62 -> SLIT("f30"); 63 -> SLIT("f31");
	_  -> SLIT("very naughty powerpc register")
      })
348
349
350
351
352
353
#else
    ppr_reg_no :: Int -> Doc
    ppr_reg_no i | i <= 31 = int i	-- GPRs
                 | i <= 63 = int (i-32) -- FPRs
		 | otherwise = ptext SLIT("very naughty powerpc register")
#endif
354
#endif
355
356


357
358
359
-- -----------------------------------------------------------------------------
-- pprSize: print a 'Size'

360
#if powerpc_TARGET_ARCH || i386_TARGET_ARCH || x86_64_TARGET_ARCH || sparc_TARGET_ARCH
361
362
pprSize :: MachRep -> Doc
#else
363
pprSize :: Size -> Doc
364
#endif
365

sof's avatar
sof committed
366
pprSize x = ptext (case x of
367
368
#if alpha_TARGET_ARCH
	 B  -> SLIT("b")
369
	 Bu -> SLIT("bu")
370
--	 W  -> SLIT("w") UNUSED
371
--	 Wu -> SLIT("wu") UNUSED
372
	 L  -> SLIT("l")
373
374
375
376
377
378
379
	 Q  -> SLIT("q")
--	 FF -> SLIT("f") UNUSED
--	 DF -> SLIT("d") UNUSED
--	 GF -> SLIT("g") UNUSED
--	 SF -> SLIT("s") UNUSED
	 TF -> SLIT("t")
#endif
380
#if i386_TARGET_ARCH || x86_64_TARGET_ARCH
381
382
383
	I8   -> SLIT("b")
	I16  -> SLIT("w")
	I32  -> SLIT("l")
384
385
386
	I64  -> SLIT("q")
#endif
#if i386_TARGET_ARCH
387
388
	F32  -> SLIT("s")
	F64  -> SLIT("l")
389
	F80  -> SLIT("t")
390
#endif
391
392
393
394
#if x86_64_TARGET_ARCH
	F32  -> SLIT("ss")	-- "scalar single-precision float" (SSE2)
	F64  -> SLIT("sd")	-- "scalar double-precision float" (SSE2)
#endif
395
#if sparc_TARGET_ARCH
396
397
398
399
400
	I8   -> SLIT("sb")
        I16   -> SLIT("sh")
	I32   -> SLIT("")
	F32   -> SLIT("")
	F64  -> SLIT("d")
sof's avatar
sof committed
401
    )
402
pprStSize :: MachRep -> Doc
sof's avatar
sof committed
403
pprStSize x = ptext (case x of
404
405
406
407
408
	I8   -> SLIT("b")
	I16  -> SLIT("h")
	I32  -> SLIT("")
	F32  -> SLIT("")
	F64  -> SLIT("d")
409
410
#endif
#if powerpc_TARGET_ARCH
411
412
413
414
415
	I8   -> SLIT("b")
        I16  -> SLIT("h")
	I32  -> SLIT("w")
	F32  -> SLIT("fs")
	F64  -> SLIT("fd")
416
417
418
#endif
    )

419
420
-- -----------------------------------------------------------------------------
-- pprCond: print a 'Cond'
421

422
pprCond :: Cond -> Doc
423

sof's avatar
sof committed
424
pprCond c = ptext (case c of {
425
#if alpha_TARGET_ARCH
426
427
	EQQ  -> SLIT("eq");
	LTT  -> SLIT("lt");
428
429
430
431
	LE  -> SLIT("le");
	ULT -> SLIT("ult");
	ULE -> SLIT("ule");
	NE  -> SLIT("ne");
432
	GTT  -> SLIT("gt");
433
434
	GE  -> SLIT("ge")
#endif
435
#if i386_TARGET_ARCH || x86_64_TARGET_ARCH
436
	GEU	-> SLIT("ae");	LU    -> SLIT("b");
437
	EQQ	-> SLIT("e");	GTT   -> SLIT("g");
438
	GE	-> SLIT("ge");	GU    -> SLIT("a");
439
	LTT	-> SLIT("l");	LE    -> SLIT("le");
440
441
	LEU	-> SLIT("be");	NE    -> SLIT("ne");
	NEG	-> SLIT("s");	POS   -> SLIT("ns");
442
        CARRY   -> SLIT("c");   OFLO  -> SLIT("o");
443
	PARITY  -> SLIT("p");   NOTPARITY -> SLIT("np");
444
445
446
447
448
	ALWAYS	-> SLIT("mp")	-- hack
#endif
#if sparc_TARGET_ARCH
	ALWAYS	-> SLIT("");	NEVER -> SLIT("n");
	GEU	-> SLIT("geu");	LU    -> SLIT("lu");
449
	EQQ	-> SLIT("e");	GTT   -> SLIT("g");
450
	GE	-> SLIT("ge");	GU    -> SLIT("gu");
451
	LTT	-> SLIT("l");	LE    -> SLIT("le");
452
453
454
	LEU	-> SLIT("leu");	NE    -> SLIT("ne");
	NEG	-> SLIT("neg");	POS   -> SLIT("pos");
	VC	-> SLIT("vc");	VS    -> SLIT("vs")
455
456
457
458
459
460
461
462
#endif
#if powerpc_TARGET_ARCH
	ALWAYS  -> SLIT("");
	EQQ	-> SLIT("eq");	NE    -> SLIT("ne");
	LTT     -> SLIT("lt");  GE    -> SLIT("ge");
	GTT     -> SLIT("gt");  LE    -> SLIT("le");
	LU      -> SLIT("lt");  GEU   -> SLIT("ge");
	GU      -> SLIT("gt");  LEU   -> SLIT("le");
463
464
465
466
#endif
    })


467
468
469
-- -----------------------------------------------------------------------------
-- pprImm: print an 'Imm'

470
pprImm :: Imm -> Doc
471

sof's avatar
sof committed
472
473
pprImm (ImmInt i)     = int i
pprImm (ImmInteger i) = integer i
474
475
pprImm (ImmCLbl l)    = pprCLabel_asm l
pprImm (ImmIndex l i) = pprCLabel_asm l <> char '+' <> int i
476
477
pprImm (ImmLit s)     = s

478
479
pprImm (ImmFloat _) = ptext SLIT("naughty float immediate")
pprImm (ImmDouble _) = ptext SLIT("naughty double immediate")
480

481
pprImm (ImmConstantSum a b) = pprImm a <> char '+' <> pprImm b
482
483
484
485
486
#if sparc_TARGET_ARCH
-- ToDo: This should really be fixed in the PIC support, but only
-- print a for now.
pprImm (ImmConstantDiff a b) = pprImm a 
#else
487
488
pprImm (ImmConstantDiff a b) = pprImm a <> char '-'
                            <> lparen <> pprImm b <> rparen
489
#endif
490

491
492
#if sparc_TARGET_ARCH
pprImm (LO i)
sof's avatar
sof committed
493
  = hcat [ pp_lo, pprImm i, rparen ]
494
  where
495
    pp_lo = text "%lo("
496
497

pprImm (HI i)
sof's avatar
sof committed
498
  = hcat [ pp_hi, pprImm i, rparen ]
499
  where
500
    pp_hi = text "%hi("
501
#endif
502
#if powerpc_TARGET_ARCH
503
#if darwin_TARGET_OS
504
505
506
507
508
509
510
511
512
513
514
515
516
517
pprImm (LO i)
  = hcat [ pp_lo, pprImm i, rparen ]
  where
    pp_lo = text "lo16("

pprImm (HI i)
  = hcat [ pp_hi, pprImm i, rparen ]
  where
    pp_hi = text "hi16("

pprImm (HA i)
  = hcat [ pp_ha, pprImm i, rparen ]
  where
    pp_ha = text "ha16("
518
    
519
520
521
522
523
524
525
526
527
528
#else
pprImm (LO i)
  = pprImm i <> text "@l"

pprImm (HI i)
  = pprImm i <> text "@h"

pprImm (HA i)
  = pprImm i <> text "@ha"
#endif
529
#endif
530
531


532
533
534
535
-- -----------------------------------------------------------------------------
-- @pprAddr: print an 'AddrMode'

pprAddr :: AddrMode -> Doc
536
537

#if alpha_TARGET_ARCH
sof's avatar
sof committed
538
pprAddr (AddrReg r) = parens (pprReg r)
539
540
pprAddr (AddrImm i) = pprImm i
pprAddr (AddrRegImm r1 i)
sof's avatar
sof committed
541
  = (<>) (pprImm i) (parens (pprReg r1))
542
543
544
545
#endif

-------------------

546
#if i386_TARGET_ARCH || x86_64_TARGET_ARCH
547
pprAddr (ImmAddr imm off)
548
  = let	pp_imm = pprImm imm
549
550
551
552
    in
    if (off == 0) then
	pp_imm
    else if (off < 0) then
553
	pp_imm <> int off
554
    else
555
	pp_imm <> char '+' <> int off
556

557
pprAddr (AddrBaseIndex base index displacement)
558
559
  = let
	pp_disp  = ppr_disp displacement
560
	pp_off p = pp_disp <> char '(' <> p <> char ')'
561
	pp_reg r = pprReg wordRep r
562
563
    in
    case (base,index) of
564
565
566
567
568
      (EABaseNone,  EAIndexNone) -> pp_disp
      (EABaseReg b, EAIndexNone) -> pp_off (pp_reg b)
      (EABaseRip,   EAIndexNone) -> pp_off (ptext SLIT("%rip"))
      (EABaseNone,  EAIndex r i) -> pp_off (comma <> pp_reg r <> comma <> int i)
      (EABaseReg b, EAIndex r i) -> pp_off (pp_reg b <> comma <> pp_reg r 
569
                                       <> comma <> int i)
570
  where
sof's avatar
sof committed
571
    ppr_disp (ImmInt 0) = empty
572
573
574
575
576
577
    ppr_disp imm        = pprImm imm
#endif

-------------------

#if sparc_TARGET_ARCH
578
pprAddr (AddrRegReg r1 (RealReg 0)) = pprReg r1
579
580

pprAddr (AddrRegReg r1 r2)
sof's avatar
sof committed
581
  = hcat [ pprReg r1, char '+', pprReg r2 ]
582
583
584
585

pprAddr (AddrRegImm r1 (ImmInt i))
  | i == 0 = pprReg r1
  | not (fits13Bits i) = largeOffsetError i
sof's avatar
sof committed
586
  | otherwise = hcat [ pprReg r1, pp_sign, int i ]
587
  where
sof's avatar
sof committed
588
    pp_sign = if i > 0 then char '+' else empty
589
590
591
592

pprAddr (AddrRegImm r1 (ImmInteger i))
  | i == 0 = pprReg r1
  | not (fits13Bits i) = largeOffsetError i
sof's avatar
sof committed
593
  | otherwise  = hcat [ pprReg r1, pp_sign, integer i ]
594
  where
sof's avatar
sof committed
595
    pp_sign = if i > 0 then char '+' else empty
596
597

pprAddr (AddrRegImm r1 imm)
sof's avatar
sof committed
598
  = hcat [ pprReg r1, char '+', pprImm imm ]
599
#endif
600
601
602

-------------------

603
604
#if powerpc_TARGET_ARCH
pprAddr (AddrRegReg r1 r2)
605
  = pprReg r1 <+> ptext SLIT(", ") <+> pprReg r2
606
607
608
609
610

pprAddr (AddrRegImm r1 (ImmInt i)) = hcat [ int i, char '(', pprReg r1, char ')' ]
pprAddr (AddrRegImm r1 (ImmInteger i)) = hcat [ integer i, char '(', pprReg r1, char ')' ]
pprAddr (AddrRegImm r1 imm) = hcat [ pprImm imm, char '(', pprReg r1, char ')' ]
#endif
611

612

613
614
-- -----------------------------------------------------------------------------
-- pprData: print a 'CmmStatic'
615

616
617
618
619
pprSectionHeader Text
    = ptext
	IF_ARCH_alpha(SLIT("\t.text\n\t.align 3") {-word boundary-}
       ,IF_ARCH_sparc(SLIT(".text\n\t.align 4") {-word boundary-}
620
621
622
       ,IF_ARCH_i386(IF_OS_darwin(SLIT(".text\n\t.align 2"),
                                  SLIT(".text\n\t.align 4,0x90"))
                                  {-needs per-OS variation!-}
623
624
       ,IF_ARCH_x86_64(IF_OS_darwin(SLIT(".text\n.align 3"),
                                    SLIT(".text\n\t.align 8"))
625
       ,IF_ARCH_powerpc(SLIT(".text\n.align 2")
626
       ,)))))
627
pprSectionHeader Data
sof's avatar
sof committed
628
    = ptext
629
	 IF_ARCH_alpha(SLIT("\t.data\n\t.align 3")
630
	,IF_ARCH_sparc(SLIT(".data\n\t.align 8") {-<8 will break double constants -}
631
632
	,IF_ARCH_i386(IF_OS_darwin(SLIT(".data\n\t.align 2"),
                                   SLIT(".data\n\t.align 4"))
633
634
	,IF_ARCH_x86_64(IF_OS_darwin(SLIT(".data\n.align 3"),
	                             SLIT(".data\n\t.align 8"))
635
        ,IF_ARCH_powerpc(SLIT(".data\n.align 2")
636
	,)))))
637
pprSectionHeader ReadOnlyData
638
639
640
    = ptext
	 IF_ARCH_alpha(SLIT("\t.data\n\t.align 3")
	,IF_ARCH_sparc(SLIT(".data\n\t.align 8") {-<8 will break double constants -}
641
642
	,IF_ARCH_i386(IF_OS_darwin(SLIT(".const\n.align 2"),
                                   SLIT(".section .rodata\n\t.align 4"))
643
644
	,IF_ARCH_x86_64(IF_OS_darwin(SLIT(".const\n.align 3"),
	                             SLIT(".section .rodata\n\t.align 8"))
645
        ,IF_ARCH_powerpc(IF_OS_darwin(SLIT(".const\n.align 2"),
646
                                      SLIT(".section .rodata\n\t.align 2"))
647
	,)))))
648
649
650
651
pprSectionHeader RelocatableReadOnlyData
    = ptext
	 IF_ARCH_alpha(SLIT("\t.data\n\t.align 3")
	,IF_ARCH_sparc(SLIT(".data\n\t.align 8") {-<8 will break double constants -}
652
	,IF_ARCH_i386(IF_OS_darwin(SLIT(".const_data\n.align 2"),
653
                                   SLIT(".section .data\n\t.align 4"))
654
	,IF_ARCH_x86_64(IF_OS_darwin(SLIT(".const_data\n.align 3"),
655
                                     SLIT(".section .data\n\t.align 8"))
656
657
        ,IF_ARCH_powerpc(IF_OS_darwin(SLIT(".const_data\n.align 2"),
                                      SLIT(".data\n\t.align 2"))
658
	,)))))
659
660
661
662
pprSectionHeader UninitialisedData
    = ptext
	 IF_ARCH_alpha(SLIT("\t.bss\n\t.align 3")
	,IF_ARCH_sparc(SLIT(".bss\n\t.align 8") {-<8 will break double constants -}
663
	,IF_ARCH_i386(IF_OS_darwin(SLIT(".data\n\t.align 2"),
664
                                   SLIT(".section .bss\n\t.align 4"))
665
666
	,IF_ARCH_x86_64(IF_OS_darwin(SLIT(".data\n\t.align 3"),
                                     SLIT(".section .bss\n\t.align 8"))
667
668
        ,IF_ARCH_powerpc(IF_OS_darwin(SLIT(".const_data\n.align 2"),
                                      SLIT(".section .bss\n\t.align 2"))
669
670
671
672
673
	,)))))
pprSectionHeader ReadOnlyData16
    = ptext
	 IF_ARCH_alpha(SLIT("\t.data\n\t.align 4")
	,IF_ARCH_sparc(SLIT(".data\n\t.align 16")
674
675
	,IF_ARCH_i386(IF_OS_darwin(SLIT(".const\n.align 4"),
                                   SLIT(".section .rodata\n\t.align 16"))
676
677
	,IF_ARCH_x86_64(IF_OS_darwin(SLIT(".const\n.align 4"),
	                             SLIT(".section .rodata.cst16\n\t.align 16"))
678
679
680
681
        ,IF_ARCH_powerpc(IF_OS_darwin(SLIT(".const\n.align 4"),
                                      SLIT(".section .rodata\n\t.align 4"))
	,)))))

682
683
684
685
686
687
688
689
690
691
692
693
694
pprSectionHeader (OtherSection sec)
    = panic "PprMach.pprSectionHeader: unknown section"

pprData :: CmmStatic -> Doc
pprData (CmmAlign bytes)         = pprAlign bytes
pprData (CmmDataLabel lbl)       = pprLabel lbl
pprData (CmmString str)          = pprASCII str
pprData (CmmUninitialised bytes) = ptext SLIT(".space ") <> int bytes
pprData (CmmStaticLit lit)       = pprDataItem lit

pprGloblDecl :: CLabel -> Doc
pprGloblDecl lbl
  | not (externallyVisibleCLabel lbl) = empty
695
696
  | otherwise = ptext IF_ARCH_sparc(SLIT(".global "), 
				    SLIT(".globl ")) <>
697
		pprCLabel_asm lbl
698

699
700
pprTypeAndSizeDecl :: CLabel -> Doc
pprTypeAndSizeDecl lbl
701
#if linux_TARGET_OS
702
703
704
  | not (externallyVisibleCLabel lbl) = empty
  | otherwise = ptext SLIT(".type ") <>
		pprCLabel_asm lbl <> ptext SLIT(", @object")
705
706
#else
  = empty
707
#endif
708

709
pprLabel :: CLabel -> Doc
710
pprLabel lbl = pprGloblDecl lbl $$ pprTypeAndSizeDecl lbl $$ (pprCLabel_asm lbl <> char ':')
711

712
713

pprASCII str
714
  = vcat (map do1 str) $$ do1 0
715
    where
716
717
       do1 :: Word8 -> Doc
       do1 w = ptext SLIT("\t.byte\t") <> int (fromIntegral w)
718

719
720
pprAlign bytes =
	IF_ARCH_alpha(ptextSLIT(".align ") <> int pow2,
721
	IF_ARCH_i386(ptext SLIT(".align ") <> int IF_OS_darwin(pow2,bytes),
722
	IF_ARCH_x86_64(ptext SLIT(".align ") <> int IF_OS_darwin(pow2,bytes),
723
	IF_ARCH_sparc(ptext SLIT(".align ") <> int bytes,
724
	IF_ARCH_powerpc(ptext SLIT(".align ") <> int pow2,)))))
725
726
727
728
729
730
731
732
733
  where
	pow2 = log2 bytes
	
	log2 :: Int -> Int  -- cache the common ones
	log2 1 = 0 
	log2 2 = 1
	log2 4 = 2
	log2 8 = 3
	log2 n = 1 + log2 (n `quot` 2)
734

735
736
737
738

pprDataItem :: CmmLit -> Doc
pprDataItem lit
  = vcat (ppr_item (cmmLitRep lit) lit)
739
    where
740
	imm = litToImm lit
741

742
743
744
745
	-- These seem to be common:
	ppr_item I8   x = [ptext SLIT("\t.byte\t") <> pprImm imm]
	ppr_item I32  x = [ptext SLIT("\t.long\t") <> pprImm imm]
	ppr_item F32  (CmmFloat r _)
746
           = let bs = floatToBytes (fromRational r)
747
             in  map (\b -> ptext SLIT("\t.byte\t") <> pprImm (ImmInt b)) bs
748
    	ppr_item F64 (CmmFloat r _)
749
           = let bs = doubleToBytes (fromRational r)
750
             in  map (\b -> ptext SLIT("\t.byte\t") <> pprImm (ImmInt b)) bs
751
752
753
754
755

#if sparc_TARGET_ARCH
        -- copy n paste of x86 version
	ppr_item I16  x = [ptext SLIT("\t.short\t") <> pprImm imm]
	ppr_item I64  x = [ptext SLIT("\t.quad\t") <> pprImm imm]
756
#endif
757
#if i386_TARGET_ARCH || x86_64_TARGET_ARCH
758
	ppr_item I16  x = [ptext SLIT("\t.word\t") <> pprImm imm]
759
#endif
760
761
762
763
764
765
766
767
#if i386_TARGET_ARCH && darwin_TARGET_OS
        ppr_item I64 (CmmInt x _)  =
                [ptext SLIT("\t.long\t")
                    <> int (fromIntegral (fromIntegral x :: Word32)),
                 ptext SLIT("\t.long\t")
                    <> int (fromIntegral
                        (fromIntegral (x `shiftR` 32) :: Word32))]
#endif
768
#if i386_TARGET_ARCH || (darwin_TARGET_OS && x86_64_TARGET_ARCH)
769
	ppr_item I64  x = [ptext SLIT("\t.quad\t") <> pprImm imm]
770
#endif
771
#if x86_64_TARGET_ARCH && !darwin_TARGET_OS
772
773
774
775
776
	-- x86_64: binutils can't handle the R_X86_64_PC64 relocation
	-- type, which means we can't do pc-relative 64-bit addresses.
	-- Fortunately we're assuming the small memory model, in which
	-- all such offsets will fit into 32 bits, so we have to stick
	-- to 32-bit offset fields and modify the RTS appropriately
777
778
        --
        -- See Note [x86-64-relative] in includes/InfoTables.h
779
780
781
782
783
784
785
786
787
788
789
	-- 
	ppr_item I64  x 
	   | isRelativeReloc x =
		[ptext SLIT("\t.long\t") <> pprImm imm,
		 ptext SLIT("\t.long\t0")]
	   | otherwise =
		[ptext SLIT("\t.quad\t") <> pprImm imm]
	   where
		isRelativeReloc (CmmLabelDiffOff _ _ _) = True
		isRelativeReloc _ = False
#endif
790
#if powerpc_TARGET_ARCH
791
792
793
794
795
796
797
	ppr_item I16 x = [ptext SLIT("\t.short\t") <> pprImm imm]
        ppr_item I64 (CmmInt x _)  =
                [ptext SLIT("\t.long\t")
                    <> int (fromIntegral 
                        (fromIntegral (x `shiftR` 32) :: Word32)),
                 ptext SLIT("\t.long\t")
                    <> int (fromIntegral (fromIntegral x :: Word32))]
798
#endif
799

800
801
-- fall through to rest of (machine-specific) pprInstr...

802
803
804
-- -----------------------------------------------------------------------------
-- pprInstr: print an 'Instr'

805
806
807
instance Outputable Instr where
    ppr	 instr	= Outputable.docToSDoc $ pprInstr instr

808
809
810
811
812
813
814
pprInstr :: Instr -> Doc

--pprInstr (COMMENT s) = empty -- nuke 'em
pprInstr (COMMENT s)
   =  IF_ARCH_alpha( ((<>) (ptext SLIT("\t# ")) (ftext s))
     ,IF_ARCH_sparc( ((<>) (ptext SLIT("! "))   (ftext s))
     ,IF_ARCH_i386( ((<>) (ptext SLIT("# "))   (ftext s))
815
     ,IF_ARCH_x86_64( ((<>) (ptext SLIT("# "))   (ftext s))
816
817
818
     ,IF_ARCH_powerpc( IF_OS_linux(
        ((<>) (ptext SLIT("# ")) (ftext s)),
        ((<>) (ptext SLIT("; ")) (ftext s)))
819
     ,)))))
820
821
822
823
824
825
826
827
828
829
830
831

pprInstr (DELTA d)
   = pprInstr (COMMENT (mkFastString ("\tdelta = " ++ show d)))

pprInstr (NEWBLOCK _)
   = panic "PprMach.pprInstr: NEWBLOCK"

pprInstr (LDATA _ _)
   = panic "PprMach.pprInstr: LDATA"

-- -----------------------------------------------------------------------------
-- pprInstr for an Alpha
832
833
834

#if alpha_TARGET_ARCH

835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
pprInstr (SPILL reg slot)
   = hcat [
   	ptext SLIT("\tSPILL"),
	char '\t',
	pprReg reg,
	comma,
	ptext SLIT("SLOT") <> parens (int slot)]

pprInstr (RELOAD slot reg)
   = hcat [
   	ptext SLIT("\tRELOAD"),
	char '\t',
	ptext SLIT("SLOT") <> parens (int slot),
	comma,
	pprReg reg]

851
pprInstr (LD size reg addr)
sof's avatar
sof committed
852
853
  = hcat [
	ptext SLIT("\tld"),
854
	pprSize size,
sof's avatar
sof committed
855
	char '\t',
856
	pprReg reg,
sof's avatar
sof committed
857
	comma,
858
859
860
861
	pprAddr addr
    ]

pprInstr (LDA reg addr)
sof's avatar
sof committed
862
863
  = hcat [
	ptext SLIT("\tlda\t"),
864
	pprReg reg,
sof's avatar
sof committed
865
	comma,
866
867
868
869
	pprAddr addr
    ]

pprInstr (LDAH reg addr)
sof's avatar
sof committed
870
871
  = hcat [
	ptext SLIT("\tldah\t"),
872
	pprReg reg,
sof's avatar
sof committed
873
	comma,
874
875
876
877
	pprAddr addr
    ]

pprInstr (LDGP reg addr)
sof's avatar
sof committed
878
879
  = hcat [
	ptext SLIT("\tldgp\t"),
880
	pprReg reg,
sof's avatar
sof committed
881
	comma,
882
883
884
885
	pprAddr addr
    ]

pprInstr (LDI size reg imm)
sof's avatar
sof committed
886
887
  = hcat [
	ptext SLIT("\tldi"),
888
	pprSize size,
sof's avatar
sof committed
889
	char '\t',
890
	pprReg reg,
sof's avatar
sof committed
891
	comma,
892
893
894
895
	pprImm imm
    ]

pprInstr (ST size reg addr)
sof's avatar
sof committed
896
897
  = hcat [
	ptext SLIT("\tst"),
898
	pprSize size,
sof's avatar
sof committed
899
	char '\t',
900
	pprReg reg,
sof's avatar
sof committed
901
	comma,
902
903
904
905
	pprAddr addr
    ]

pprInstr (CLR reg)
sof's avatar
sof committed
906
907
  = hcat [
	ptext SLIT("\tclr\t"),
908
909
910
911
	pprReg reg
    ]

pprInstr (ABS size ri reg)
sof's avatar
sof committed
912
913
  = hcat [
	ptext SLIT("\tabs"),
914
	pprSize size,
sof's avatar
sof committed
915
	char '\t',
916
	pprRI ri,
sof's avatar
sof committed
917
	comma,
918
919
920
921
	pprReg reg
    ]

pprInstr (NEG size ov ri reg)
sof's avatar
sof committed
922
923
  = hcat [
	ptext SLIT("\tneg"),
924
	pprSize size,
sof's avatar
sof committed
925
	if ov then ptext SLIT("v\t") else char '\t',
926
	pprRI ri,
sof's avatar
sof committed
927
	comma,
928
929
930
931
	pprReg reg
    ]

pprInstr (ADD size ov reg1 ri reg2)
sof's avatar
sof committed
932
933
  = hcat [
	ptext SLIT("\tadd"),
934
	pprSize size,
sof's avatar
sof committed
935
	if ov then ptext SLIT("v\t") else char '\t',
936
	pprReg reg1,
sof's avatar
sof committed
937
	comma,
938
	pprRI ri,
sof's avatar
sof committed
939
	comma,
940
941
942
943
	pprReg reg2
    ]

pprInstr (SADD size scale reg1 ri reg2)
sof's avatar
sof committed
944
945
946
  = hcat [
	ptext (case scale of {{-UNUSED:L -> SLIT("\ts4");-} Q -> SLIT("\ts8")}),
	ptext SLIT("add"),
947
	pprSize size,
sof's avatar
sof committed
948
	char '\t',
949
	pprReg reg1,
sof's avatar
sof committed
950
	comma,
951
	pprRI ri,
sof's avatar
sof committed
952
	comma,
953
954
955
956
	pprReg reg2
    ]

pprInstr (SUB size ov reg1 ri reg2)
sof's avatar
sof committed
957
958
  = hcat [
	ptext SLIT("\tsub"),
959
	pprSize size,
sof's avatar
sof committed
960
	if ov then ptext SLIT("v\t") else char '\t',
961
	pprReg reg1,
sof's avatar
sof committed
962
	comma,
963
	pprRI ri,
sof's avatar
sof committed
964
	comma,
965
966
967
968
	pprReg reg2
    ]

pprInstr (SSUB size scale reg1 ri reg2)
sof's avatar
sof committed
969
970
971
  = hcat [
	ptext (case scale of {{-UNUSED:L -> SLIT("\ts4");-} Q -> SLIT("\ts8")}),
	ptext SLIT("sub"),
972
	pprSize size,
sof's avatar
sof committed
973
	char '\t',
974
	pprReg reg1,
sof's avatar
sof committed
975
	comma,
976
	pprRI ri,
sof's avatar
sof committed
977
	comma,
978
979
980
981
	pprReg reg2
    ]

pprInstr (MUL size ov reg1 ri reg2)
sof's avatar
sof committed
982
983
  = hcat [
	ptext SLIT("\tmul"),
984
	pprSize size,
sof's avatar
sof committed
985
	if ov then ptext SLIT("v\t") else char '\t',
986
	pprReg reg1,
sof's avatar
sof committed
987
	comma,
988
	pprRI ri,
sof's avatar
sof committed
989
	comma,
990
991
992
993
	pprReg reg2
    ]

pprInstr (DIV size uns reg1 ri reg2)
sof's avatar
sof committed
994
995
  = hcat [
	ptext SLIT("\tdiv"),
996
	pprSize size,
sof's avatar
sof committed
997
	if uns then ptext SLIT("u\t") else char '\t',
998
	pprReg reg1,
sof's avatar
sof committed
999
	comma,
1000
	pprRI ri,
sof's avatar
sof committed
1001
	comma,
1002
1003
1004
1005
	pprReg reg2
    ]

pprInstr (REM size uns reg1 ri reg2)
sof's avatar
sof committed
1006
1007
  = hcat [
	ptext SLIT("\trem"),
1008
	pprSize size,
sof's avatar
sof committed
1009
	if uns then ptext SLIT("u\t") else char '\t',
1010
	pprReg reg1,
sof's avatar
sof committed
1011
	comma,
1012
	pprRI ri,
sof's avatar
sof committed
1013
	comma,
1014
1015
1016
1017
	pprReg reg2
    ]

pprInstr (NOT ri reg)
sof's avatar
sof committed
1018
1019
1020
  = hcat [
	ptext SLIT("\tnot"),
	char '\t',
1021
	pprRI ri,
sof's avatar
sof committed
1022
	comma,
1023
1024
1025
1026
1027
1028
1029 <