2 % (c) The AQUA Project, Glasgow University, 1996-1998
4 \section[PprMach]{Pretty-printing assembly language}
6 We start with the @pprXXX@s with some cross-platform commonality
7 (e.g., @pprReg@); we conclude with the no-commonality monster,
11 #include "nativeGen/NCG.h"
13 module PprMach ( pprInstr, pprSize, pprUserReg ) where
15 #include "HsVersions.h"
17 import MachRegs -- may differ per-platform
20 import CLabel ( pprCLabel, externallyVisibleCLabel, labelDynamic )
21 import Stix ( CodeSegment(..) )
22 import Unique ( pprUnique )
23 import Panic ( panic )
25 import qualified Outputable
29 import Char ( chr, ord )
30 import Maybe ( isJust )
32 asmSDoc d = Outputable.withPprStyleDoc (
33 Outputable.mkCodeStyle Outputable.AsmStyle) d
34 pprCLabel_asm l = asmSDoc (pprCLabel l)
37 %************************************************************************
39 \subsection{@pprReg@: print a @Reg@}
41 %************************************************************************
43 For x86, the way we print a register name depends
44 on which bit of it we care about. Yurgh.
46 pprUserReg :: Reg -> Doc
47 pprUserReg = pprReg IF_ARCH_i386(L,)
49 pprReg :: IF_ARCH_i386(Size ->,) Reg -> Doc
51 pprReg IF_ARCH_i386(s,) r
53 RealReg i -> ppr_reg_no IF_ARCH_i386(s,) i
54 VirtualRegI u -> text "%vI_" <> asmSDoc (pprVRegUnique u)
55 VirtualRegF u -> text "%vF_" <> asmSDoc (pprVRegUnique u)
58 ppr_reg_no :: Int -> Doc
61 0 -> SLIT("$0"); 1 -> SLIT("$1");
62 2 -> SLIT("$2"); 3 -> SLIT("$3");
63 4 -> SLIT("$4"); 5 -> SLIT("$5");
64 6 -> SLIT("$6"); 7 -> SLIT("$7");
65 8 -> SLIT("$8"); 9 -> SLIT("$9");
66 10 -> SLIT("$10"); 11 -> SLIT("$11");
67 12 -> SLIT("$12"); 13 -> SLIT("$13");
68 14 -> SLIT("$14"); 15 -> SLIT("$15");
69 16 -> SLIT("$16"); 17 -> SLIT("$17");
70 18 -> SLIT("$18"); 19 -> SLIT("$19");
71 20 -> SLIT("$20"); 21 -> SLIT("$21");
72 22 -> SLIT("$22"); 23 -> SLIT("$23");
73 24 -> SLIT("$24"); 25 -> SLIT("$25");
74 26 -> SLIT("$26"); 27 -> SLIT("$27");
75 28 -> SLIT("$28"); 29 -> SLIT("$29");
76 30 -> SLIT("$30"); 31 -> SLIT("$31");
77 32 -> SLIT("$f0"); 33 -> SLIT("$f1");
78 34 -> SLIT("$f2"); 35 -> SLIT("$f3");
79 36 -> SLIT("$f4"); 37 -> SLIT("$f5");
80 38 -> SLIT("$f6"); 39 -> SLIT("$f7");
81 40 -> SLIT("$f8"); 41 -> SLIT("$f9");
82 42 -> SLIT("$f10"); 43 -> SLIT("$f11");
83 44 -> SLIT("$f12"); 45 -> SLIT("$f13");
84 46 -> SLIT("$f14"); 47 -> SLIT("$f15");
85 48 -> SLIT("$f16"); 49 -> SLIT("$f17");
86 50 -> SLIT("$f18"); 51 -> SLIT("$f19");
87 52 -> SLIT("$f20"); 53 -> SLIT("$f21");
88 54 -> SLIT("$f22"); 55 -> SLIT("$f23");
89 56 -> SLIT("$f24"); 57 -> SLIT("$f25");
90 58 -> SLIT("$f26"); 59 -> SLIT("$f27");
91 60 -> SLIT("$f28"); 61 -> SLIT("$f29");
92 62 -> SLIT("$f30"); 63 -> SLIT("$f31");
93 _ -> SLIT("very naughty alpha register")
97 ppr_reg_no :: Size -> Int -> Doc
98 ppr_reg_no B = ppr_reg_byte
99 ppr_reg_no Bu = ppr_reg_byte
100 ppr_reg_no W = ppr_reg_word
101 ppr_reg_no Wu = ppr_reg_word
102 ppr_reg_no _ = ppr_reg_long
104 ppr_reg_byte i = ptext
106 0 -> SLIT("%al"); 1 -> SLIT("%bl");
107 2 -> SLIT("%cl"); 3 -> SLIT("%dl");
108 _ -> SLIT("very naughty I386 byte register")
111 ppr_reg_word i = ptext
113 0 -> SLIT("%ax"); 1 -> SLIT("%bx");
114 2 -> SLIT("%cx"); 3 -> SLIT("%dx");
115 4 -> SLIT("%si"); 5 -> SLIT("%di");
116 6 -> SLIT("%bp"); 7 -> SLIT("%sp");
117 _ -> SLIT("very naughty I386 word register")
120 ppr_reg_long i = ptext
122 0 -> SLIT("%eax"); 1 -> SLIT("%ebx");
123 2 -> SLIT("%ecx"); 3 -> SLIT("%edx");
124 4 -> SLIT("%esi"); 5 -> SLIT("%edi");
125 6 -> SLIT("%ebp"); 7 -> SLIT("%esp");
126 8 -> SLIT("%fake0"); 9 -> SLIT("%fake1");
127 10 -> SLIT("%fake2"); 11 -> SLIT("%fake3");
128 12 -> SLIT("%fake4"); 13 -> SLIT("%fake5");
129 _ -> SLIT("very naughty I386 register")
132 #if sparc_TARGET_ARCH
133 ppr_reg_no :: Int -> Doc
136 0 -> SLIT("%g0"); 1 -> SLIT("%g1");
137 2 -> SLIT("%g2"); 3 -> SLIT("%g3");
138 4 -> SLIT("%g4"); 5 -> SLIT("%g5");
139 6 -> SLIT("%g6"); 7 -> SLIT("%g7");
140 8 -> SLIT("%o0"); 9 -> SLIT("%o1");
141 10 -> SLIT("%o2"); 11 -> SLIT("%o3");
142 12 -> SLIT("%o4"); 13 -> SLIT("%o5");
143 14 -> SLIT("%o6"); 15 -> SLIT("%o7");
144 16 -> SLIT("%l0"); 17 -> SLIT("%l1");
145 18 -> SLIT("%l2"); 19 -> SLIT("%l3");
146 20 -> SLIT("%l4"); 21 -> SLIT("%l5");
147 22 -> SLIT("%l6"); 23 -> SLIT("%l7");
148 24 -> SLIT("%i0"); 25 -> SLIT("%i1");
149 26 -> SLIT("%i2"); 27 -> SLIT("%i3");
150 28 -> SLIT("%i4"); 29 -> SLIT("%i5");
151 30 -> SLIT("%i6"); 31 -> SLIT("%i7");
152 32 -> SLIT("%f0"); 33 -> SLIT("%f1");
153 34 -> SLIT("%f2"); 35 -> SLIT("%f3");
154 36 -> SLIT("%f4"); 37 -> SLIT("%f5");
155 38 -> SLIT("%f6"); 39 -> SLIT("%f7");
156 40 -> SLIT("%f8"); 41 -> SLIT("%f9");
157 42 -> SLIT("%f10"); 43 -> SLIT("%f11");
158 44 -> SLIT("%f12"); 45 -> SLIT("%f13");
159 46 -> SLIT("%f14"); 47 -> SLIT("%f15");
160 48 -> SLIT("%f16"); 49 -> SLIT("%f17");
161 50 -> SLIT("%f18"); 51 -> SLIT("%f19");
162 52 -> SLIT("%f20"); 53 -> SLIT("%f21");
163 54 -> SLIT("%f22"); 55 -> SLIT("%f23");
164 56 -> SLIT("%f24"); 57 -> SLIT("%f25");
165 58 -> SLIT("%f26"); 59 -> SLIT("%f27");
166 60 -> SLIT("%f28"); 61 -> SLIT("%f29");
167 62 -> SLIT("%f30"); 63 -> SLIT("%f31");
168 _ -> SLIT("very naughty sparc register")
173 %************************************************************************
175 \subsection{@pprSize@: print a @Size@}
177 %************************************************************************
180 pprSize :: Size -> Doc
182 pprSize x = ptext (case x of
183 #if alpha_TARGET_ARCH
186 -- W -> SLIT("w") UNUSED
187 -- Wu -> SLIT("wu") UNUSED
190 -- FF -> SLIT("f") UNUSED
191 -- DF -> SLIT("d") UNUSED
192 -- GF -> SLIT("g") UNUSED
193 -- SF -> SLIT("s") UNUSED
207 #if sparc_TARGET_ARCH
216 pprStSize :: Size -> Doc
217 pprStSize x = ptext (case x of
229 %************************************************************************
231 \subsection{@pprCond@: print a @Cond@}
233 %************************************************************************
236 pprCond :: Cond -> Doc
238 pprCond c = ptext (case c of {
239 #if alpha_TARGET_ARCH
250 GEU -> SLIT("ae"); LU -> SLIT("b");
251 EQQ -> SLIT("e"); GTT -> SLIT("g");
252 GE -> SLIT("ge"); GU -> SLIT("a");
253 LTT -> SLIT("l"); LE -> SLIT("le");
254 LEU -> SLIT("be"); NE -> SLIT("ne");
255 NEG -> SLIT("s"); POS -> SLIT("ns");
256 CARRY -> SLIT("c"); OFLO -> SLIT("o");
257 ALWAYS -> SLIT("mp") -- hack
259 #if sparc_TARGET_ARCH
260 ALWAYS -> SLIT(""); NEVER -> SLIT("n");
261 GEU -> SLIT("geu"); LU -> SLIT("lu");
262 EQQ -> SLIT("e"); GTT -> SLIT("g");
263 GE -> SLIT("ge"); GU -> SLIT("gu");
264 LTT -> SLIT("l"); LE -> SLIT("le");
265 LEU -> SLIT("leu"); NE -> SLIT("ne");
266 NEG -> SLIT("neg"); POS -> SLIT("pos");
267 VC -> SLIT("vc"); VS -> SLIT("vs")
272 %************************************************************************
274 \subsection{@pprImm@: print an @Imm@}
276 %************************************************************************
281 pprImm (ImmInt i) = int i
282 pprImm (ImmInteger i) = integer i
283 pprImm (ImmCLbl l) = (if labelDynamic l then text "__imp_" else empty)
285 pprImm (ImmIndex l i) = (if labelDynamic l then text "__imp_" else empty)
286 <> pprCLabel_asm l <> char '+' <> int i
287 pprImm (ImmLit s) = s
289 pprImm (ImmLab dll s) = (if underscorePrefix then char '_' else empty)
290 <> (if dll then text "_imp__" else empty)
293 #if sparc_TARGET_ARCH
295 = hcat [ pp_lo, pprImm i, rparen ]
300 = hcat [ pp_hi, pprImm i, rparen ]
306 %************************************************************************
308 \subsection{@pprAddr@: print an @Addr@}
310 %************************************************************************
313 pprAddr :: MachRegsAddr -> Doc
315 #if alpha_TARGET_ARCH
316 pprAddr (AddrReg r) = parens (pprReg r)
317 pprAddr (AddrImm i) = pprImm i
318 pprAddr (AddrRegImm r1 i)
319 = (<>) (pprImm i) (parens (pprReg r1))
325 pprAddr (ImmAddr imm off)
326 = let pp_imm = pprImm imm
330 else if (off < 0) then
333 pp_imm <> char '+' <> int off
335 pprAddr (AddrBaseIndex base index displacement)
337 pp_disp = ppr_disp displacement
338 pp_off p = pp_disp <> char '(' <> p <> char ')'
339 pp_reg r = pprReg L r
342 (Nothing, Nothing) -> pp_disp
343 (Just b, Nothing) -> pp_off (pp_reg b)
344 (Nothing, Just (r,i)) -> pp_off (pp_reg r <> comma <> int i)
345 (Just b, Just (r,i)) -> pp_off (pp_reg b <> comma <> pp_reg r
348 ppr_disp (ImmInt 0) = empty
349 ppr_disp imm = pprImm imm
354 #if sparc_TARGET_ARCH
355 pprAddr (AddrRegReg r1 (RealReg 0)) = pprReg r1
357 pprAddr (AddrRegReg r1 r2)
358 = hcat [ pprReg r1, char '+', pprReg r2 ]
360 pprAddr (AddrRegImm r1 (ImmInt i))
362 | not (fits13Bits i) = largeOffsetError i
363 | otherwise = hcat [ pprReg r1, pp_sign, int i ]
365 pp_sign = if i > 0 then char '+' else empty
367 pprAddr (AddrRegImm r1 (ImmInteger i))
369 | not (fits13Bits i) = largeOffsetError i
370 | otherwise = hcat [ pprReg r1, pp_sign, integer i ]
372 pp_sign = if i > 0 then char '+' else empty
374 pprAddr (AddrRegImm r1 imm)
375 = hcat [ pprReg r1, char '+', pprImm imm ]
379 %************************************************************************
381 \subsection{@pprInstr@: print an @Instr@}
383 %************************************************************************
386 pprInstr :: Instr -> Doc
388 --pprInstr (COMMENT s) = empty -- nuke 'em
390 = IF_ARCH_alpha( ((<>) (ptext SLIT("\t# ")) (ptext s))
391 ,IF_ARCH_sparc( ((<>) (ptext SLIT("! ")) (ptext s))
392 ,IF_ARCH_i386( ((<>) (ptext SLIT("# ")) (ptext s))
396 = pprInstr (COMMENT (_PK_ ("\tdelta = " ++ show d)))
398 pprInstr (SEGMENT TextSegment)
399 = IF_ARCH_alpha(ptext SLIT("\t.text\n\t.align 3") {-word boundary-}
400 ,IF_ARCH_sparc(ptext SLIT(".text\n\t.align 4") {-word boundary-}
401 ,IF_ARCH_i386((text ".text\n\t.align 4,0x90") {-needs per-OS variation!-}
404 pprInstr (SEGMENT DataSegment)
406 IF_ARCH_alpha(SLIT("\t.data\n\t.align 3")
407 ,IF_ARCH_sparc(SLIT(".data\n\t.align 8") {-<8 will break double constants -}
408 ,IF_ARCH_i386(SLIT(".data\n\t.align 4")
411 pprInstr (SEGMENT RoDataSegment)
413 IF_ARCH_alpha(SLIT("\t.data\n\t.align 3")
414 ,IF_ARCH_sparc(SLIT(".data\n\t.align 8") {-<8 will break double constants -}
415 ,IF_ARCH_i386(SLIT(".section .rodata\n\t.align 4")
418 pprInstr (LABEL clab)
420 pp_lab = pprCLabel_asm clab
423 if not (externallyVisibleCLabel clab) then
427 IF_ARCH_alpha(SLIT("\t.globl\t")
428 ,IF_ARCH_i386(SLIT(".globl ")
429 ,IF_ARCH_sparc(SLIT(".global\t")
431 , pp_lab, char '\n'],
436 pprInstr (ASCII False{-no backslash conversion-} str)
437 = hcat [ ptext SLIT("\t.asciz "), char '\"', text str, char '"' ]
439 pprInstr (ASCII True str)
440 = vcat (map do1 (str ++ [chr 0]))
443 do1 c = ptext SLIT("\t.byte\t0x") <> hshow (ord c)
446 hshow n | n >= 0 && n <= 255
447 = char (tab !! (n `div` 16)) <> char (tab !! (n `mod` 16))
448 tab = "0123456789ABCDEF"
452 = vcat (concatMap (ppr_item s) xs)
455 #if alpha_TARGET_ARCH
456 ppr_item = error "ppr_item on Alpha"
458 #if sparc_TARGET_ARCH
459 -- copy n paste of x86 version
460 ppr_item B x = [ptext SLIT("\t.byte\t") <> pprImm x]
461 ppr_item W x = [ptext SLIT("\t.long\t") <> pprImm x]
462 ppr_item F (ImmFloat r)
463 = let bs = floatToBytes (fromRational r)
464 in map (\b -> ptext SLIT("\t.byte\t") <> pprImm (ImmInt b)) bs
465 ppr_item DF (ImmDouble r)
466 = let bs = doubleToBytes (fromRational r)
467 in map (\b -> ptext SLIT("\t.byte\t") <> pprImm (ImmInt b)) bs
470 ppr_item B x = [ptext SLIT("\t.byte\t") <> pprImm x]
471 ppr_item L x = [ptext SLIT("\t.long\t") <> pprImm x]
472 ppr_item F (ImmFloat r)
473 = let bs = floatToBytes (fromRational r)
474 in map (\b -> ptext SLIT("\t.byte\t") <> pprImm (ImmInt b)) bs
475 ppr_item DF (ImmDouble r)
476 = let bs = doubleToBytes (fromRational r)
477 in map (\b -> ptext SLIT("\t.byte\t") <> pprImm (ImmInt b)) bs
480 -- floatToBytes and doubleToBytes convert to the host's byte
481 -- order. Providing that we're not cross-compiling for a
482 -- target with the opposite endianness, this should work ok
484 floatToBytes :: Float -> [Int]
487 arr <- newFloatArray ((0::Int),3)
488 writeFloatArray arr 0 f
489 i0 <- readCharArray arr 0
490 i1 <- readCharArray arr 1
491 i2 <- readCharArray arr 2
492 i3 <- readCharArray arr 3
493 return (map ord [i0,i1,i2,i3])
496 doubleToBytes :: Double -> [Int]
499 arr <- newDoubleArray ((0::Int),7)
500 writeDoubleArray arr 0 d
501 i0 <- readCharArray arr 0
502 i1 <- readCharArray arr 1
503 i2 <- readCharArray arr 2
504 i3 <- readCharArray arr 3
505 i4 <- readCharArray arr 4
506 i5 <- readCharArray arr 5
507 i6 <- readCharArray arr 6
508 i7 <- readCharArray arr 7
509 return (map ord [i0,i1,i2,i3,i4,i5,i6,i7])
512 -- fall through to rest of (machine-specific) pprInstr...
515 %************************************************************************
517 \subsubsection{@pprInstr@ for an Alpha}
519 %************************************************************************
522 #if alpha_TARGET_ARCH
524 pprInstr (LD size reg addr)
534 pprInstr (LDA reg addr)
536 ptext SLIT("\tlda\t"),
542 pprInstr (LDAH reg addr)
544 ptext SLIT("\tldah\t"),
550 pprInstr (LDGP reg addr)
552 ptext SLIT("\tldgp\t"),
558 pprInstr (LDI size reg imm)
568 pprInstr (ST size reg addr)
580 ptext SLIT("\tclr\t"),
584 pprInstr (ABS size ri reg)
594 pprInstr (NEG size ov ri reg)
598 if ov then ptext SLIT("v\t") else char '\t',
604 pprInstr (ADD size ov reg1 ri reg2)
608 if ov then ptext SLIT("v\t") else char '\t',
616 pprInstr (SADD size scale reg1 ri reg2)
618 ptext (case scale of {{-UNUSED:L -> SLIT("\ts4");-} Q -> SLIT("\ts8")}),
629 pprInstr (SUB size ov reg1 ri reg2)
633 if ov then ptext SLIT("v\t") else char '\t',
641 pprInstr (SSUB size scale reg1 ri reg2)
643 ptext (case scale of {{-UNUSED:L -> SLIT("\ts4");-} Q -> SLIT("\ts8")}),
654 pprInstr (MUL size ov reg1 ri reg2)
658 if ov then ptext SLIT("v\t") else char '\t',
666 pprInstr (DIV size uns reg1 ri reg2)
670 if uns then ptext SLIT("u\t") else char '\t',
678 pprInstr (REM size uns reg1 ri reg2)
682 if uns then ptext SLIT("u\t") else char '\t',
690 pprInstr (NOT ri reg)
699 pprInstr (AND reg1 ri reg2) = pprRegRIReg SLIT("and") reg1 ri reg2
700 pprInstr (ANDNOT reg1 ri reg2) = pprRegRIReg SLIT("andnot") reg1 ri reg2
701 pprInstr (OR reg1 ri reg2) = pprRegRIReg SLIT("or") reg1 ri reg2
702 pprInstr (ORNOT reg1 ri reg2) = pprRegRIReg SLIT("ornot") reg1 ri reg2
703 pprInstr (XOR reg1 ri reg2) = pprRegRIReg SLIT("xor") reg1 ri reg2
704 pprInstr (XORNOT reg1 ri reg2) = pprRegRIReg SLIT("xornot") reg1 ri reg2
706 pprInstr (SLL reg1 ri reg2) = pprRegRIReg SLIT("sll") reg1 ri reg2
707 pprInstr (SRL reg1 ri reg2) = pprRegRIReg SLIT("srl") reg1 ri reg2
708 pprInstr (SRA reg1 ri reg2) = pprRegRIReg SLIT("sra") reg1 ri reg2
710 pprInstr (ZAP reg1 ri reg2) = pprRegRIReg SLIT("zap") reg1 ri reg2
711 pprInstr (ZAPNOT reg1 ri reg2) = pprRegRIReg SLIT("zapnot") reg1 ri reg2
713 pprInstr (NOP) = ptext SLIT("\tnop")
715 pprInstr (CMP cond reg1 ri reg2)
729 ptext SLIT("\tfclr\t"),
733 pprInstr (FABS reg1 reg2)
735 ptext SLIT("\tfabs\t"),
741 pprInstr (FNEG size reg1 reg2)
751 pprInstr (FADD size reg1 reg2 reg3) = pprSizeRegRegReg SLIT("add") size reg1 reg2 reg3
752 pprInstr (FDIV size reg1 reg2 reg3) = pprSizeRegRegReg SLIT("div") size reg1 reg2 reg3
753 pprInstr (FMUL size reg1 reg2 reg3) = pprSizeRegRegReg SLIT("mul") size reg1 reg2 reg3
754 pprInstr (FSUB size reg1 reg2 reg3) = pprSizeRegRegReg SLIT("sub") size reg1 reg2 reg3
756 pprInstr (CVTxy size1 size2 reg1 reg2)
760 case size2 of {Q -> ptext SLIT("qc"); _ -> pprSize size2},
767 pprInstr (FCMP size cond reg1 reg2 reg3)
780 pprInstr (FMOV reg1 reg2)
782 ptext SLIT("\tfmov\t"),
788 pprInstr (BI ALWAYS reg lab) = pprInstr (BR lab)
790 pprInstr (BI NEVER reg lab) = empty
792 pprInstr (BI cond reg lab)
802 pprInstr (BF cond reg lab)
813 = (<>) (ptext SLIT("\tbr\t")) (pprImm lab)
815 pprInstr (JMP reg addr hint)
817 ptext SLIT("\tjmp\t"),
826 = (<>) (ptext SLIT("\tbsr\t")) (pprImm imm)
828 pprInstr (JSR reg addr n)
830 ptext SLIT("\tjsr\t"),
836 pprInstr (FUNBEGIN clab)
838 if (externallyVisibleCLabel clab) then
839 hcat [ptext SLIT("\t.globl\t"), pp_lab, char '\n']
842 ptext SLIT("\t.ent "),
851 pp_lab = pprCLabel_asm clab
853 -- NEVER use commas within those string literals, cpp will ruin your day
854 pp_ldgp = hcat [ ptext SLIT(":\n\tldgp $29"), char ',', ptext SLIT("0($27)\n") ]
855 pp_frame = hcat [ ptext SLIT("..ng:\n\t.frame $30"), char ',',
856 ptext SLIT("4240"), char ',',
857 ptext SLIT("$26"), char ',',
858 ptext SLIT("0\n\t.prologue 1") ]
860 pprInstr (FUNEND clab)
861 = (<>) (ptext SLIT("\t.align 4\n\t.end ")) (pprCLabel_asm clab)
864 Continue with Alpha-only printing bits and bobs:
868 pprRI (RIReg r) = pprReg r
869 pprRI (RIImm r) = pprImm r
871 pprRegRIReg :: FAST_STRING -> Reg -> RI -> Reg -> Doc
873 pprRegRIReg name reg1 ri reg2
885 pprSizeRegRegReg :: FAST_STRING -> Size -> Reg -> Reg -> Reg -> Doc
887 pprSizeRegRegReg name size reg1 reg2 reg3
900 #endif {-alpha_TARGET_ARCH-}
903 %************************************************************************
905 \subsubsection{@pprInstr@ for an I386}
907 %************************************************************************
912 pprInstr v@(MOV size s@(OpReg src) d@(OpReg dst)) -- hack
915 #if 0 /* #ifdef DEBUG */
916 (<>) (ptext SLIT("# warning: ")) (pprSizeOpOp SLIT("mov") size s d)
920 pprInstr (MOV size src dst)
921 = pprSizeOpOp SLIT("mov") size src dst
922 pprInstr (MOVZxL sizes src dst) = pprSizeOpOpCoerce SLIT("movz") sizes L src dst
923 pprInstr (MOVSxL sizes src dst) = pprSizeOpOpCoerce SLIT("movs") sizes L src dst
925 -- here we do some patching, since the physical registers are only set late
926 -- in the code generation.
927 pprInstr (LEA size (OpAddr (AddrBaseIndex src1@(Just reg1) (Just (reg2,1)) (ImmInt 0))) dst@(OpReg reg3))
929 = pprSizeOpOp SLIT("add") size (OpReg reg2) dst
930 pprInstr (LEA size (OpAddr (AddrBaseIndex src1@(Just reg1) (Just (reg2,1)) (ImmInt 0))) dst@(OpReg reg3))
932 = pprSizeOpOp SLIT("add") size (OpReg reg1) dst
933 pprInstr (LEA size (OpAddr (AddrBaseIndex src1@(Just reg1) Nothing displ)) dst@(OpReg reg3))
935 = pprInstr (ADD size (OpImm displ) dst)
936 pprInstr (LEA size src dst) = pprSizeOpOp SLIT("lea") size src dst
938 pprInstr (ADD size (OpImm (ImmInt (-1))) dst)
939 = pprSizeOp SLIT("dec") size dst
940 pprInstr (ADD size (OpImm (ImmInt 1)) dst)
941 = pprSizeOp SLIT("inc") size dst
942 pprInstr (ADD size src dst)
943 = pprSizeOpOp SLIT("add") size src dst
944 pprInstr (SUB size src dst) = pprSizeOpOp SLIT("sub") size src dst
945 pprInstr (IMUL size op1 op2) = pprSizeOpOp SLIT("imul") size op1 op2
947 {- A hack. The Intel documentation says that "The two and three
948 operand forms [of IMUL] may also be used with unsigned operands
949 because the lower half of the product is the same regardless if
950 (sic) the operands are signed or unsigned. The CF and OF flags,
951 however, cannot be used to determine if the upper half of the
952 result is non-zero." So there.
954 pprInstr (MUL size op1 op2) = pprSizeOpOp SLIT("imul") size op1 op2
956 pprInstr (AND size src dst) = pprSizeOpOp SLIT("and") size src dst
957 pprInstr (OR size src dst) = pprSizeOpOp SLIT("or") size src dst
958 pprInstr (XOR size src dst) = pprSizeOpOp SLIT("xor") size src dst
959 pprInstr (NOT size op) = pprSizeOp SLIT("not") size op
960 pprInstr (NEGI size op) = pprSizeOp SLIT("neg") size op
962 pprInstr (SHL size imm dst) = pprSizeImmOp SLIT("shl") size imm dst
963 pprInstr (SAR size imm dst) = pprSizeImmOp SLIT("sar") size imm dst
964 pprInstr (SHR size imm dst) = pprSizeImmOp SLIT("shr") size imm dst
965 pprInstr (BT size imm src) = pprSizeImmOp SLIT("bt") size imm src
967 pprInstr (CMP size src dst) = pprSizeOpOp SLIT("cmp") size src dst
968 pprInstr (TEST size src dst) = pprSizeOpOp SLIT("test") size src dst
969 pprInstr (PUSH size op) = pprSizeOp SLIT("push") size op
970 pprInstr (POP size op) = pprSizeOp SLIT("pop") size op
971 pprInstr PUSHA = ptext SLIT("\tpushal")
972 pprInstr POPA = ptext SLIT("\tpopal")
974 pprInstr (NOP) = ptext SLIT("\tnop")
975 pprInstr (CLTD) = ptext SLIT("\tcltd")
977 pprInstr (SETCC cond op) = pprCondInstr SLIT("set") cond (pprOperand B op)
979 pprInstr (JXX cond lab) = pprCondInstr SLIT("j") cond (pprCLabel_asm lab)
981 pprInstr (JMP dsts (OpImm imm)) = (<>) (ptext SLIT("\tjmp ")) (pprImm imm)
982 pprInstr (JMP dsts op) = (<>) (ptext SLIT("\tjmp *")) (pprOperand L op)
983 pprInstr (CALL imm) = (<>) (ptext SLIT("\tcall ")) (pprImm imm)
985 -- First bool indicates signedness; second whether quot or rem
986 pprInstr (IQUOT sz src dst) = pprInstr_quotRem True True sz src dst
987 pprInstr (IREM sz src dst) = pprInstr_quotRem True False sz src dst
989 pprInstr (QUOT sz src dst) = pprInstr_quotRem False True sz src dst
990 pprInstr (REM sz src dst) = pprInstr_quotRem False False sz src dst
992 pprInstr (IMUL64 sd_hi sd_lo) = pprInstr_imul64 sd_hi sd_lo
995 -- Simulating a flat register set on the x86 FP stack is tricky.
996 -- you have to free %st(7) before pushing anything on the FP reg stack
997 -- so as to preclude the possibility of a FP stack overflow exception.
998 pprInstr g@(GMOV src dst)
1002 = pprG g (hcat [gtab, gpush src 0, gsemi, gpop dst 1])
1004 -- GLD sz addr dst ==> FFREE %st(7) ; FLDsz addr ; FSTP (dst+1)
1005 pprInstr g@(GLD sz addr dst)
1006 = pprG g (hcat [gtab, text "ffree %st(7) ; fld", pprSize sz, gsp,
1007 pprAddr addr, gsemi, gpop dst 1])
1009 -- GST sz src addr ==> FFREE %st(7) ; FLD dst ; FSTPsz addr
1010 pprInstr g@(GST sz src addr)
1011 = pprG g (hcat [gtab, gpush src 0, gsemi,
1012 text "fstp", pprSize sz, gsp, pprAddr addr])
1014 pprInstr g@(GLDZ dst)
1015 = pprG g (hcat [gtab, text "ffree %st(7) ; fldz ; ", gpop dst 1])
1016 pprInstr g@(GLD1 dst)
1017 = pprG g (hcat [gtab, text "ffree %st(7) ; fld1 ; ", gpop dst 1])
1019 pprInstr g@(GFTOI src dst)
1020 = pprInstr (GDTOI src dst)
1021 pprInstr g@(GDTOI src dst)
1022 = pprG g (hcat [gtab, text "subl $4, %esp ; ",
1023 gpush src 0, gsemi, text "fistpl 0(%esp) ; popl ",
1026 pprInstr g@(GITOF src dst)
1027 = pprInstr (GITOD src dst)
1028 pprInstr g@(GITOD src dst)
1029 = pprG g (hcat [gtab, text "pushl ", pprReg L src,
1030 text " ; ffree %st(7); fildl (%esp) ; ",
1031 gpop dst 1, text " ; addl $4,%esp"])
1033 pprInstr g@(GCMP sz src1 src2)
1034 = pprG g (hcat [gtab, text "pushl %eax ; ",gpush src1 0]
1036 hcat [gtab, text "fcomp ", greg src2 1,
1037 text "; fstsw %ax ; sahf ; popl %eax"])
1039 pprInstr g@(GABS sz src dst)
1040 = pprG g (hcat [gtab, gpush src 0, text " ; fabs ; ", gpop dst 1])
1041 pprInstr g@(GNEG sz src dst)
1042 = pprG g (hcat [gtab, gpush src 0, text " ; fchs ; ", gpop dst 1])
1044 pprInstr g@(GSQRT sz src dst)
1045 = pprG g (hcat [gtab, gpush src 0, text " ; fsqrt"] $$
1046 hcat [gtab, gcoerceto sz, gpop dst 1])
1047 pprInstr g@(GSIN sz src dst)
1048 = pprG g (hcat [gtab, gpush src 0, text " ; fsin"] $$
1049 hcat [gtab, gcoerceto sz, gpop dst 1])
1050 pprInstr g@(GCOS sz src dst)
1051 = pprG g (hcat [gtab, gpush src 0, text " ; fcos"] $$
1052 hcat [gtab, gcoerceto sz, gpop dst 1])
1053 pprInstr g@(GTAN sz src dst)
1054 = pprG g (hcat [gtab, text "ffree %st(6) ; ",
1055 gpush src 0, text " ; fptan ; ",
1056 text " fstp %st(0)"] $$
1057 hcat [gtab, gcoerceto sz, gpop dst 1])
1059 -- In the translations for GADD, GMUL, GSUB and GDIV,
1060 -- the first two cases are mere optimisations. The otherwise clause
1061 -- generates correct code under all circumstances.
1063 pprInstr g@(GADD sz src1 src2 dst)
1065 = pprG g (text "\t#GADD-xxxcase1" $$
1066 hcat [gtab, gpush src2 0,
1067 text " ; faddp %st(0),", greg src1 1])
1069 = pprG g (text "\t#GADD-xxxcase2" $$
1070 hcat [gtab, gpush src1 0,
1071 text " ; faddp %st(0),", greg src2 1])
1073 = pprG g (hcat [gtab, gpush src1 0,
1074 text " ; fadd ", greg src2 1, text ",%st(0)",
1078 pprInstr g@(GMUL sz src1 src2 dst)
1080 = pprG g (text "\t#GMUL-xxxcase1" $$
1081 hcat [gtab, gpush src2 0,
1082 text " ; fmulp %st(0),", greg src1 1])
1084 = pprG g (text "\t#GMUL-xxxcase2" $$
1085 hcat [gtab, gpush src1 0,
1086 text " ; fmulp %st(0),", greg src2 1])
1088 = pprG g (hcat [gtab, gpush src1 0,
1089 text " ; fmul ", greg src2 1, text ",%st(0)",
1093 pprInstr g@(GSUB sz src1 src2 dst)
1095 = pprG g (text "\t#GSUB-xxxcase1" $$
1096 hcat [gtab, gpush src2 0,
1097 text " ; fsubrp %st(0),", greg src1 1])
1099 = pprG g (text "\t#GSUB-xxxcase2" $$
1100 hcat [gtab, gpush src1 0,
1101 text " ; fsubp %st(0),", greg src2 1])
1103 = pprG g (hcat [gtab, gpush src1 0,
1104 text " ; fsub ", greg src2 1, text ",%st(0)",
1108 pprInstr g@(GDIV sz src1 src2 dst)
1110 = pprG g (text "\t#GDIV-xxxcase1" $$
1111 hcat [gtab, gpush src2 0,
1112 text " ; fdivrp %st(0),", greg src1 1])
1114 = pprG g (text "\t#GDIV-xxxcase2" $$
1115 hcat [gtab, gpush src1 0,
1116 text " ; fdivp %st(0),", greg src2 1])
1118 = pprG g (hcat [gtab, gpush src1 0,
1119 text " ; fdiv ", greg src2 1, text ",%st(0)",
1124 = vcat [ ptext SLIT("\tffree %st(0) ;ffree %st(1) ;ffree %st(2) ;ffree %st(3)"),
1125 ptext SLIT("\tffree %st(4) ;ffree %st(5) ;ffree %st(6) ;ffree %st(7)")
1129 pprInstr_quotRem signed isQuot sz src dst
1130 | case sz of L -> False; _ -> True
1131 = panic "pprInstr_quotRem: dunno how to do non-32bit operands"
1134 (text "\t# BEGIN " <> fakeInsn),
1135 (text "\tpushl $0; pushl %eax; pushl %edx; pushl " <> pprOperand sz src),
1136 (text "\tmovl " <> pprOperand sz dst <> text ",%eax; " <> widen_to_64),
1137 (x86op <> text " 0(%esp); movl " <> text resReg <> text ",12(%esp)"),
1138 (text "\tpopl %edx; popl %edx; popl %eax; popl " <> pprOperand sz dst),
1139 (text "\t# END " <> fakeInsn)
1142 widen_to_64 | signed = text "cltd"
1143 | not signed = text "xorl %edx,%edx"
1144 x86op = if signed then text "\tidivl" else text "\tdivl"
1145 resReg = if isQuot then "%eax" else "%edx"
1146 opStr | signed = if isQuot then "IQUOT" else "IREM"
1147 | not signed = if isQuot then "QUOT" else "REM"
1148 fakeInsn = text opStr <+> pprOperand sz src
1149 <> char ',' <+> pprOperand sz dst
1151 -- Emit code to make hi_reg:lo_reg be the 64-bit product of hi_reg and lo_reg
1152 pprInstr_imul64 hi_reg lo_reg
1153 = let fakeInsn = text "imul64" <+> pp_hi_reg <> comma <+> pp_lo_reg
1154 pp_hi_reg = pprReg L hi_reg
1155 pp_lo_reg = pprReg L lo_reg
1158 text "\t# BEGIN " <> fakeInsn,
1159 text "\tpushl" <+> pp_hi_reg <> text" ; pushl" <+> pp_lo_reg,
1160 text "\tpushl %eax ; pushl %edx",
1161 text "\tmovl 12(%esp), %eax ; imull 8(%esp)",
1162 text "\tmovl %edx, 12(%esp) ; movl %eax, 8(%esp)",
1163 text "\tpopl %edx ; popl %eax",
1164 text "\tpopl" <+> pp_lo_reg <> text " ; popl" <+> pp_hi_reg,
1165 text "\t# END " <> fakeInsn
1169 --------------------------
1171 -- coerce %st(0) to the specified size
1172 gcoerceto DF = empty
1173 gcoerceto F = empty --text "subl $4,%esp ; fstps (%esp) ; flds (%esp) ; addl $4,%esp ; "
1176 = hcat [text "ffree %st(7) ; fld ", greg reg offset]
1178 = hcat [text "fstp ", greg reg offset]
1180 bogus = text "\tbogus"
1181 greg reg offset = text "%st(" <> int (gregno reg - 8+offset) <> char ')'
1186 gregno (RealReg i) = i
1187 gregno other = --pprPanic "gregno" (ppr other)
1188 999 -- bogus; only needed for debug printing
1190 pprG :: Instr -> Doc -> Doc
1192 = (char '#' <> pprGInstr fake) $$ actual
1194 pprGInstr (GMOV src dst) = pprSizeRegReg SLIT("gmov") DF src dst
1195 pprGInstr (GLD sz src dst) = pprSizeAddrReg SLIT("gld") sz src dst
1196 pprGInstr (GST sz src dst) = pprSizeRegAddr SLIT("gst") sz src dst
1198 pprGInstr (GLDZ dst) = pprSizeReg SLIT("gldz") DF dst
1199 pprGInstr (GLD1 dst) = pprSizeReg SLIT("gld1") DF dst
1201 pprGInstr (GFTOI src dst) = pprSizeSizeRegReg SLIT("gftoi") F L src dst
1202 pprGInstr (GDTOI src dst) = pprSizeSizeRegReg SLIT("gdtoi") DF L src dst
1204 pprGInstr (GITOF src dst) = pprSizeSizeRegReg SLIT("gitof") L F src dst
1205 pprGInstr (GITOD src dst) = pprSizeSizeRegReg SLIT("gitod") L DF src dst
1207 pprGInstr (GCMP sz src dst) = pprSizeRegReg SLIT("gcmp") sz src dst
1208 pprGInstr (GABS sz src dst) = pprSizeRegReg SLIT("gabs") sz src dst
1209 pprGInstr (GNEG sz src dst) = pprSizeRegReg SLIT("gneg") sz src dst
1210 pprGInstr (GSQRT sz src dst) = pprSizeRegReg SLIT("gsqrt") sz src dst
1211 pprGInstr (GSIN sz src dst) = pprSizeRegReg SLIT("gsin") sz src dst
1212 pprGInstr (GCOS sz src dst) = pprSizeRegReg SLIT("gcos") sz src dst
1213 pprGInstr (GTAN sz src dst) = pprSizeRegReg SLIT("gtan") sz src dst
1215 pprGInstr (GADD sz src1 src2 dst) = pprSizeRegRegReg SLIT("gadd") sz src1 src2 dst
1216 pprGInstr (GSUB sz src1 src2 dst) = pprSizeRegRegReg SLIT("gsub") sz src1 src2 dst
1217 pprGInstr (GMUL sz src1 src2 dst) = pprSizeRegRegReg SLIT("gmul") sz src1 src2 dst
1218 pprGInstr (GDIV sz src1 src2 dst) = pprSizeRegRegReg SLIT("gdiv") sz src1 src2 dst
1221 Continue with I386-only printing bits and bobs:
1223 pprDollImm :: Imm -> Doc
1225 pprDollImm i = ptext SLIT("$") <> pprImm i
1227 pprOperand :: Size -> Operand -> Doc
1228 pprOperand s (OpReg r) = pprReg s r
1229 pprOperand s (OpImm i) = pprDollImm i
1230 pprOperand s (OpAddr ea) = pprAddr ea
1232 pprSizeImmOp :: FAST_STRING -> Size -> Imm -> Operand -> Doc
1233 pprSizeImmOp name size imm op1
1245 pprSizeOp :: FAST_STRING -> Size -> Operand -> Doc
1246 pprSizeOp name size op1
1255 pprSizeOpOp :: FAST_STRING -> Size -> Operand -> Operand -> Doc
1256 pprSizeOpOp name size op1 op2
1262 pprOperand size op1,
1267 pprSizeByteOpOp :: FAST_STRING -> Size -> Operand -> Operand -> Doc
1268 pprSizeByteOpOp name size op1 op2
1279 pprSizeOpReg :: FAST_STRING -> Size -> Operand -> Reg -> Doc
1280 pprSizeOpReg name size op1 reg
1286 pprOperand size op1,
1291 pprSizeReg :: FAST_STRING -> Size -> Reg -> Doc
1292 pprSizeReg name size reg1
1301 pprSizeRegReg :: FAST_STRING -> Size -> Reg -> Reg -> Doc
1302 pprSizeRegReg name size reg1 reg2
1313 pprSizeSizeRegReg :: FAST_STRING -> Size -> Size -> Reg -> Reg -> Doc
1314 pprSizeSizeRegReg name size1 size2 reg1 reg2
1326 pprSizeRegRegReg :: FAST_STRING -> Size -> Reg -> Reg -> Reg -> Doc
1327 pprSizeRegRegReg name size reg1 reg2 reg3
1340 pprSizeAddr :: FAST_STRING -> Size -> MachRegsAddr -> Doc
1341 pprSizeAddr name size op
1350 pprSizeAddrReg :: FAST_STRING -> Size -> MachRegsAddr -> Reg -> Doc
1351 pprSizeAddrReg name size op dst
1362 pprSizeRegAddr :: FAST_STRING -> Size -> Reg -> MachRegsAddr -> Doc
1363 pprSizeRegAddr name size src op
1374 pprOpOp :: FAST_STRING -> Size -> Operand -> Operand -> Doc
1375 pprOpOp name size op1 op2
1379 pprOperand size op1,
1384 pprSizeOpOpCoerce :: FAST_STRING -> Size -> Size -> Operand -> Operand -> Doc
1385 pprSizeOpOpCoerce name size1 size2 op1 op2
1386 = hcat [ char '\t', ptext name, pprSize size1, pprSize size2, space,
1387 pprOperand size1 op1,
1389 pprOperand size2 op2
1392 pprCondInstr :: FAST_STRING -> Cond -> Doc -> Doc
1393 pprCondInstr name cond arg
1394 = hcat [ char '\t', ptext name, pprCond cond, space, arg]
1396 #endif {-i386_TARGET_ARCH-}
1399 %************************************************************************
1401 \subsubsection{@pprInstr@ for a SPARC}
1403 %************************************************************************
1406 #if sparc_TARGET_ARCH
1408 -- a clumsy hack for now, to handle possible double alignment problems
1410 -- even clumsier, to allow for RegReg regs that show when doing indexed
1411 -- reads (bytearrays).
1414 -- Translate to the following:
1417 -- ld [g1+4],%f(n+1)
1418 -- sub g1,g2,g1 -- to restore g1
1419 pprInstr (LD DF (AddrRegReg g1 g2) reg)
1421 hcat [ptext SLIT("\tadd\t"), pprReg g1,comma,pprReg g2,comma,pprReg g1],
1422 hcat [pp_ld_lbracket, pprReg g1, pp_rbracket_comma, pprReg reg],
1423 hcat [pp_ld_lbracket, pprReg g1, ptext SLIT("+4]"), comma, pprReg (fPair reg)],
1424 hcat [ptext SLIT("\tsub\t"), pprReg g1,comma,pprReg g2,comma,pprReg g1]
1429 -- ld [addr+4],%f(n+1)
1430 pprInstr (LD DF addr reg) | isJust off_addr
1432 hcat [pp_ld_lbracket, pprAddr addr, pp_rbracket_comma, pprReg reg],
1433 hcat [pp_ld_lbracket, pprAddr addr2, pp_rbracket_comma,pprReg (fPair reg)]
1436 off_addr = addrOffset addr 4
1437 addr2 = case off_addr of Just x -> x
1440 pprInstr (LD size addr reg)
1451 -- The same clumsy hack as above
1453 -- Translate to the following:
1456 -- st %f(n+1),[g1+4]
1457 -- sub g1,g2,g1 -- to restore g1
1458 pprInstr (ST DF reg (AddrRegReg g1 g2))
1460 hcat [ptext SLIT("\tadd\t"), pprReg g1,comma,pprReg g2,comma,pprReg g1],
1461 hcat [ptext SLIT("\tst\t"), pprReg reg, pp_comma_lbracket,
1463 hcat [ptext SLIT("\tst\t"), pprReg (fPair reg), pp_comma_lbracket,
1464 pprReg g1, ptext SLIT("+4]")],
1465 hcat [ptext SLIT("\tsub\t"), pprReg g1,comma,pprReg g2,comma,pprReg g1]
1470 -- st %f(n+1),[addr+4]
1471 pprInstr (ST DF reg addr) | isJust off_addr
1473 hcat [ptext SLIT("\tst\t"), pprReg reg, pp_comma_lbracket,
1474 pprAddr addr, rbrack],
1475 hcat [ptext SLIT("\tst\t"), pprReg (fPair reg), pp_comma_lbracket,
1476 pprAddr addr2, rbrack]
1479 off_addr = addrOffset addr 4
1480 addr2 = case off_addr of Just x -> x
1482 -- no distinction is made between signed and unsigned bytes on stores for the
1483 -- Sparc opcodes (at least I cannot see any, and gas is nagging me --SOF),
1484 -- so we call a special-purpose pprSize for ST..
1486 pprInstr (ST size reg addr)
1497 pprInstr (ADD x cc reg1 ri reg2)
1498 | not x && not cc && riZero ri
1499 = hcat [ ptext SLIT("\tmov\t"), pprReg reg1, comma, pprReg reg2 ]
1501 = pprRegRIReg (if x then SLIT("addx") else SLIT("add")) cc reg1 ri reg2
1503 pprInstr (SUB x cc reg1 ri reg2)
1504 | not x && cc && reg2 == g0
1505 = hcat [ ptext SLIT("\tcmp\t"), pprReg reg1, comma, pprRI ri ]
1506 | not x && not cc && riZero ri
1507 = hcat [ ptext SLIT("\tmov\t"), pprReg reg1, comma, pprReg reg2 ]
1509 = pprRegRIReg (if x then SLIT("subx") else SLIT("sub")) cc reg1 ri reg2
1511 pprInstr (AND b reg1 ri reg2) = pprRegRIReg SLIT("and") b reg1 ri reg2
1512 pprInstr (ANDN b reg1 ri reg2) = pprRegRIReg SLIT("andn") b reg1 ri reg2
1514 pprInstr (OR b reg1 ri reg2)
1515 | not b && reg1 == g0
1516 = let doit = hcat [ ptext SLIT("\tmov\t"), pprRI ri, comma, pprReg reg2 ]
1518 RIReg rrr | rrr == reg2 -> empty
1521 = pprRegRIReg SLIT("or") b reg1 ri reg2
1523 pprInstr (ORN b reg1 ri reg2) = pprRegRIReg SLIT("orn") b reg1 ri reg2
1525 pprInstr (XOR b reg1 ri reg2) = pprRegRIReg SLIT("xor") b reg1 ri reg2
1526 pprInstr (XNOR b reg1 ri reg2) = pprRegRIReg SLIT("xnor") b reg1 ri reg2
1528 pprInstr (SLL reg1 ri reg2) = pprRegRIReg SLIT("sll") False reg1 ri reg2
1529 pprInstr (SRL reg1 ri reg2) = pprRegRIReg SLIT("srl") False reg1 ri reg2
1530 pprInstr (SRA reg1 ri reg2) = pprRegRIReg SLIT("sra") False reg1 ri reg2
1532 pprInstr (RDY rd) = ptext SLIT("\trd\t%y,") <> pprReg rd
1533 pprInstr (SMUL b reg1 ri reg2) = pprRegRIReg SLIT("smul") b reg1 ri reg2
1534 pprInstr (UMUL b reg1 ri reg2) = pprRegRIReg SLIT("umul") b reg1 ri reg2
1536 pprInstr (SETHI imm reg)
1538 ptext SLIT("\tsethi\t"),
1544 pprInstr NOP = ptext SLIT("\tnop")
1546 pprInstr (FABS F reg1 reg2) = pprSizeRegReg SLIT("fabs") F reg1 reg2
1547 pprInstr (FABS DF reg1 reg2)
1548 = (<>) (pprSizeRegReg SLIT("fabs") F reg1 reg2)
1549 (if (reg1 == reg2) then empty
1550 else (<>) (char '\n')
1551 (pprSizeRegReg SLIT("fmov") F (fPair reg1) (fPair reg2)))
1553 pprInstr (FADD size reg1 reg2 reg3)
1554 = pprSizeRegRegReg SLIT("fadd") size reg1 reg2 reg3
1555 pprInstr (FCMP e size reg1 reg2)
1556 = pprSizeRegReg (if e then SLIT("fcmpe") else SLIT("fcmp")) size reg1 reg2
1557 pprInstr (FDIV size reg1 reg2 reg3)
1558 = pprSizeRegRegReg SLIT("fdiv") size reg1 reg2 reg3
1560 pprInstr (FMOV F reg1 reg2) = pprSizeRegReg SLIT("fmov") F reg1 reg2
1561 pprInstr (FMOV DF reg1 reg2)
1562 = (<>) (pprSizeRegReg SLIT("fmov") F reg1 reg2)
1563 (if (reg1 == reg2) then empty
1564 else (<>) (char '\n')
1565 (pprSizeRegReg SLIT("fmov") F (fPair reg1) (fPair reg2)))
1567 pprInstr (FMUL size reg1 reg2 reg3)
1568 = pprSizeRegRegReg SLIT("fmul") size reg1 reg2 reg3
1570 pprInstr (FNEG F reg1 reg2) = pprSizeRegReg SLIT("fneg") F reg1 reg2
1571 pprInstr (FNEG DF reg1 reg2)
1572 = (<>) (pprSizeRegReg SLIT("fneg") F reg1 reg2)
1573 (if (reg1 == reg2) then empty
1574 else (<>) (char '\n')
1575 (pprSizeRegReg SLIT("fmov") F (fPair reg1) (fPair reg2)))
1577 pprInstr (FSQRT size reg1 reg2) = pprSizeRegReg SLIT("fsqrt") size reg1 reg2
1578 pprInstr (FSUB size reg1 reg2 reg3) = pprSizeRegRegReg SLIT("fsub") size reg1 reg2 reg3
1579 pprInstr (FxTOy size1 size2 reg1 reg2)
1592 pprReg reg1, comma, pprReg reg2
1596 pprInstr (BI cond b lab)
1598 ptext SLIT("\tb"), pprCond cond,
1599 if b then pp_comma_a else empty,
1604 pprInstr (BF cond b lab)
1606 ptext SLIT("\tfb"), pprCond cond,
1607 if b then pp_comma_a else empty,
1612 pprInstr (JMP dsts addr) = (<>) (ptext SLIT("\tjmp\t")) (pprAddr addr)
1614 pprInstr (CALL imm n _)
1615 = hcat [ ptext SLIT("\tcall\t"), pprImm imm, comma, int n ]
1618 Continue with SPARC-only printing bits and bobs:
1621 pprRI (RIReg r) = pprReg r
1622 pprRI (RIImm r) = pprImm r
1624 pprSizeRegReg :: FAST_STRING -> Size -> Reg -> Reg -> Doc
1625 pprSizeRegReg name size reg1 reg2
1630 F -> ptext SLIT("s\t")
1631 DF -> ptext SLIT("d\t")),
1637 pprSizeRegRegReg :: FAST_STRING -> Size -> Reg -> Reg -> Reg -> Doc
1638 pprSizeRegRegReg name size reg1 reg2 reg3
1643 F -> ptext SLIT("s\t")
1644 DF -> ptext SLIT("d\t")),
1652 pprRegRIReg :: FAST_STRING -> Bool -> Reg -> RI -> Reg -> Doc
1653 pprRegRIReg name b reg1 ri reg2
1657 if b then ptext SLIT("cc\t") else char '\t',
1665 pprRIReg :: FAST_STRING -> Bool -> RI -> Reg -> Doc
1666 pprRIReg name b ri reg1
1670 if b then ptext SLIT("cc\t") else char '\t',
1676 pp_ld_lbracket = ptext SLIT("\tld\t[")
1677 pp_rbracket_comma = text "],"
1678 pp_comma_lbracket = text ",["
1679 pp_comma_a = text ",a"
1681 #endif {-sparc_TARGET_ARCH-}