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 (pprUnique u)
55 VirtualRegF u -> text "%vF_" <> asmSDoc (pprUnique 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
214 pprStSize :: Size -> Doc
215 pprStSize x = ptext (case x of
225 %************************************************************************
227 \subsection{@pprCond@: print a @Cond@}
229 %************************************************************************
232 pprCond :: Cond -> Doc
234 pprCond c = ptext (case c of {
235 #if alpha_TARGET_ARCH
246 GEU -> SLIT("ae"); LU -> SLIT("b");
247 EQQ -> SLIT("e"); GTT -> SLIT("g");
248 GE -> SLIT("ge"); GU -> SLIT("a");
249 LTT -> SLIT("l"); LE -> SLIT("le");
250 LEU -> SLIT("be"); NE -> SLIT("ne");
251 NEG -> SLIT("s"); POS -> SLIT("ns");
252 CARRY -> SLIT("c"); OFLO -> SLIT("o");
253 ALWAYS -> SLIT("mp") -- hack
255 #if sparc_TARGET_ARCH
256 ALWAYS -> SLIT(""); NEVER -> SLIT("n");
257 GEU -> SLIT("geu"); LU -> SLIT("lu");
258 EQQ -> SLIT("e"); GTT -> SLIT("g");
259 GE -> SLIT("ge"); GU -> SLIT("gu");
260 LTT -> SLIT("l"); LE -> SLIT("le");
261 LEU -> SLIT("leu"); NE -> SLIT("ne");
262 NEG -> SLIT("neg"); POS -> SLIT("pos");
263 VC -> SLIT("vc"); VS -> SLIT("vs")
268 %************************************************************************
270 \subsection{@pprImm@: print an @Imm@}
272 %************************************************************************
277 pprImm (ImmInt i) = int i
278 pprImm (ImmInteger i) = integer i
279 pprImm (ImmCLbl l) = (if labelDynamic l then text "__imp_" else empty)
281 pprImm (ImmIndex l i) = (if labelDynamic l then text "__imp_" else empty)
282 <> pprCLabel_asm l <> char '+' <> int i
283 pprImm (ImmLit s) = s
285 pprImm (ImmLab dll s) = (if underscorePrefix then char '_' else empty)
286 <> (if dll then text "_imp__" else empty)
289 #if sparc_TARGET_ARCH
291 = hcat [ pp_lo, pprImm i, rparen ]
296 = hcat [ pp_hi, pprImm i, rparen ]
302 %************************************************************************
304 \subsection{@pprAddr@: print an @Addr@}
306 %************************************************************************
309 pprAddr :: MachRegsAddr -> Doc
311 #if alpha_TARGET_ARCH
312 pprAddr (AddrReg r) = parens (pprReg r)
313 pprAddr (AddrImm i) = pprImm i
314 pprAddr (AddrRegImm r1 i)
315 = (<>) (pprImm i) (parens (pprReg r1))
321 pprAddr (ImmAddr imm off)
322 = let pp_imm = pprImm imm
326 else if (off < 0) then
329 pp_imm <> char '+' <> int off
331 pprAddr (AddrBaseIndex base index displacement)
333 pp_disp = ppr_disp displacement
334 pp_off p = pp_disp <> char '(' <> p <> char ')'
335 pp_reg r = pprReg L r
338 (Nothing, Nothing) -> pp_disp
339 (Just b, Nothing) -> pp_off (pp_reg b)
340 (Nothing, Just (r,i)) -> pp_off (pp_reg r <> comma <> int i)
341 (Just b, Just (r,i)) -> pp_off (pp_reg b <> comma <> pp_reg r
344 ppr_disp (ImmInt 0) = empty
345 ppr_disp imm = pprImm imm
350 #if sparc_TARGET_ARCH
351 pprAddr (AddrRegReg r1 (RealReg 0)) = pprReg r1
353 pprAddr (AddrRegReg r1 r2)
354 = hcat [ pprReg r1, char '+', pprReg r2 ]
356 pprAddr (AddrRegImm r1 (ImmInt i))
358 | not (fits13Bits i) = largeOffsetError i
359 | otherwise = hcat [ pprReg r1, pp_sign, int i ]
361 pp_sign = if i > 0 then char '+' else empty
363 pprAddr (AddrRegImm r1 (ImmInteger i))
365 | not (fits13Bits i) = largeOffsetError i
366 | otherwise = hcat [ pprReg r1, pp_sign, integer i ]
368 pp_sign = if i > 0 then char '+' else empty
370 pprAddr (AddrRegImm r1 imm)
371 = hcat [ pprReg r1, char '+', pprImm imm ]
375 %************************************************************************
377 \subsection{@pprInstr@: print an @Instr@}
379 %************************************************************************
382 pprInstr :: Instr -> Doc
384 --pprInstr (COMMENT s) = empty -- nuke 'em
386 = IF_ARCH_alpha( ((<>) (ptext SLIT("\t# ")) (ptext s))
387 ,IF_ARCH_sparc( ((<>) (ptext SLIT("! ")) (ptext s))
388 ,IF_ARCH_i386( ((<>) (ptext SLIT("# ")) (ptext s))
392 = pprInstr (COMMENT (_PK_ ("\tdelta = " ++ show d)))
394 pprInstr (SEGMENT TextSegment)
395 = IF_ARCH_alpha(ptext SLIT("\t.text\n\t.align 3") {-word boundary-}
396 ,IF_ARCH_sparc(ptext SLIT(".text\n\t.align 4") {-word boundary-}
397 ,IF_ARCH_i386((text ".text\n\t.align 4,0x90") {-needs per-OS variation!-}
400 pprInstr (SEGMENT DataSegment)
402 IF_ARCH_alpha(SLIT("\t.data\n\t.align 3")
403 ,IF_ARCH_sparc(SLIT(".data\n\t.align 8") {-<8 will break double constants -}
404 ,IF_ARCH_i386(SLIT(".data\n\t.align 4")
407 pprInstr (SEGMENT RoDataSegment)
409 IF_ARCH_alpha(SLIT("\t.data\n\t.align 3")
410 ,IF_ARCH_sparc(SLIT(".data\n\t.align 8") {-<8 will break double constants -}
411 ,IF_ARCH_i386(SLIT(".section .rodata\n\t.align 4")
414 pprInstr (LABEL clab)
416 pp_lab = pprCLabel_asm clab
419 if not (externallyVisibleCLabel clab) then
423 IF_ARCH_alpha(SLIT("\t.globl\t")
424 ,IF_ARCH_i386(SLIT(".globl ")
425 ,IF_ARCH_sparc(SLIT(".global\t")
427 , pp_lab, char '\n'],
432 pprInstr (ASCII False{-no backslash conversion-} str)
433 = hcat [ ptext SLIT("\t.asciz "), char '\"', text str, char '"' ]
435 pprInstr (ASCII True str)
436 = vcat (map do1 (str ++ [chr 0]))
439 do1 c = ptext SLIT("\t.byte\t0x") <> hshow (ord c)
442 hshow n | n >= 0 && n <= 255
443 = char (tab !! (n `div` 16)) <> char (tab !! (n `mod` 16))
444 tab = "0123456789ABCDEF"
448 = vcat (concatMap (ppr_item s) xs)
451 #if alpha_TARGET_ARCH
452 ppr_item = error "ppr_item on Alpha"
454 #if sparc_TARGET_ARCH
455 -- copy n paste of x86 version
456 ppr_item B x = [ptext SLIT("\t.byte\t") <> pprImm x]
457 ppr_item W x = [ptext SLIT("\t.long\t") <> pprImm x]
458 ppr_item F (ImmFloat r)
459 = let bs = floatToBytes (fromRational r)
460 in map (\b -> ptext SLIT("\t.byte\t") <> pprImm (ImmInt b)) bs
461 ppr_item DF (ImmDouble r)
462 = let bs = doubleToBytes (fromRational r)
463 in map (\b -> ptext SLIT("\t.byte\t") <> pprImm (ImmInt b)) bs
466 ppr_item B x = [ptext SLIT("\t.byte\t") <> pprImm x]
467 ppr_item L x = [ptext SLIT("\t.long\t") <> pprImm x]
468 ppr_item F (ImmFloat r)
469 = let bs = floatToBytes (fromRational r)
470 in map (\b -> ptext SLIT("\t.byte\t") <> pprImm (ImmInt b)) bs
471 ppr_item DF (ImmDouble r)
472 = let bs = doubleToBytes (fromRational r)
473 in map (\b -> ptext SLIT("\t.byte\t") <> pprImm (ImmInt b)) bs
476 -- floatToBytes and doubleToBytes convert to the host's byte
477 -- order. Providing that we're not cross-compiling for a
478 -- target with the opposite endianness, this should work ok
480 floatToBytes :: Float -> [Int]
483 arr <- newFloatArray ((0::Int),3)
484 writeFloatArray arr 0 f
485 i0 <- readCharArray arr 0
486 i1 <- readCharArray arr 1
487 i2 <- readCharArray arr 2
488 i3 <- readCharArray arr 3
489 return (map ord [i0,i1,i2,i3])
492 doubleToBytes :: Double -> [Int]
495 arr <- newDoubleArray ((0::Int),7)
496 writeDoubleArray arr 0 d
497 i0 <- readCharArray arr 0
498 i1 <- readCharArray arr 1
499 i2 <- readCharArray arr 2
500 i3 <- readCharArray arr 3
501 i4 <- readCharArray arr 4
502 i5 <- readCharArray arr 5
503 i6 <- readCharArray arr 6
504 i7 <- readCharArray arr 7
505 return (map ord [i0,i1,i2,i3,i4,i5,i6,i7])
508 -- fall through to rest of (machine-specific) pprInstr...
511 %************************************************************************
513 \subsubsection{@pprInstr@ for an Alpha}
515 %************************************************************************
518 #if alpha_TARGET_ARCH
520 pprInstr (LD size reg addr)
530 pprInstr (LDA reg addr)
532 ptext SLIT("\tlda\t"),
538 pprInstr (LDAH reg addr)
540 ptext SLIT("\tldah\t"),
546 pprInstr (LDGP reg addr)
548 ptext SLIT("\tldgp\t"),
554 pprInstr (LDI size reg imm)
564 pprInstr (ST size reg addr)
576 ptext SLIT("\tclr\t"),
580 pprInstr (ABS size ri reg)
590 pprInstr (NEG size ov ri reg)
594 if ov then ptext SLIT("v\t") else char '\t',
600 pprInstr (ADD size ov reg1 ri reg2)
604 if ov then ptext SLIT("v\t") else char '\t',
612 pprInstr (SADD size scale reg1 ri reg2)
614 ptext (case scale of {{-UNUSED:L -> SLIT("\ts4");-} Q -> SLIT("\ts8")}),
625 pprInstr (SUB size ov reg1 ri reg2)
629 if ov then ptext SLIT("v\t") else char '\t',
637 pprInstr (SSUB size scale reg1 ri reg2)
639 ptext (case scale of {{-UNUSED:L -> SLIT("\ts4");-} Q -> SLIT("\ts8")}),
650 pprInstr (MUL size ov reg1 ri reg2)
654 if ov then ptext SLIT("v\t") else char '\t',
662 pprInstr (DIV size uns reg1 ri reg2)
666 if uns then ptext SLIT("u\t") else char '\t',
674 pprInstr (REM size uns reg1 ri reg2)
678 if uns then ptext SLIT("u\t") else char '\t',
686 pprInstr (NOT ri reg)
695 pprInstr (AND reg1 ri reg2) = pprRegRIReg SLIT("and") reg1 ri reg2
696 pprInstr (ANDNOT reg1 ri reg2) = pprRegRIReg SLIT("andnot") reg1 ri reg2
697 pprInstr (OR reg1 ri reg2) = pprRegRIReg SLIT("or") reg1 ri reg2
698 pprInstr (ORNOT reg1 ri reg2) = pprRegRIReg SLIT("ornot") reg1 ri reg2
699 pprInstr (XOR reg1 ri reg2) = pprRegRIReg SLIT("xor") reg1 ri reg2
700 pprInstr (XORNOT reg1 ri reg2) = pprRegRIReg SLIT("xornot") reg1 ri reg2
702 pprInstr (SLL reg1 ri reg2) = pprRegRIReg SLIT("sll") reg1 ri reg2
703 pprInstr (SRL reg1 ri reg2) = pprRegRIReg SLIT("srl") reg1 ri reg2
704 pprInstr (SRA reg1 ri reg2) = pprRegRIReg SLIT("sra") reg1 ri reg2
706 pprInstr (ZAP reg1 ri reg2) = pprRegRIReg SLIT("zap") reg1 ri reg2
707 pprInstr (ZAPNOT reg1 ri reg2) = pprRegRIReg SLIT("zapnot") reg1 ri reg2
709 pprInstr (NOP) = ptext SLIT("\tnop")
711 pprInstr (CMP cond reg1 ri reg2)
725 ptext SLIT("\tfclr\t"),
729 pprInstr (FABS reg1 reg2)
731 ptext SLIT("\tfabs\t"),
737 pprInstr (FNEG size reg1 reg2)
747 pprInstr (FADD size reg1 reg2 reg3) = pprSizeRegRegReg SLIT("add") size reg1 reg2 reg3
748 pprInstr (FDIV size reg1 reg2 reg3) = pprSizeRegRegReg SLIT("div") size reg1 reg2 reg3
749 pprInstr (FMUL size reg1 reg2 reg3) = pprSizeRegRegReg SLIT("mul") size reg1 reg2 reg3
750 pprInstr (FSUB size reg1 reg2 reg3) = pprSizeRegRegReg SLIT("sub") size reg1 reg2 reg3
752 pprInstr (CVTxy size1 size2 reg1 reg2)
756 case size2 of {Q -> ptext SLIT("qc"); _ -> pprSize size2},
763 pprInstr (FCMP size cond reg1 reg2 reg3)
776 pprInstr (FMOV reg1 reg2)
778 ptext SLIT("\tfmov\t"),
784 pprInstr (BI ALWAYS reg lab) = pprInstr (BR lab)
786 pprInstr (BI NEVER reg lab) = empty
788 pprInstr (BI cond reg lab)
798 pprInstr (BF cond reg lab)
809 = (<>) (ptext SLIT("\tbr\t")) (pprImm lab)
811 pprInstr (JMP reg addr hint)
813 ptext SLIT("\tjmp\t"),
822 = (<>) (ptext SLIT("\tbsr\t")) (pprImm imm)
824 pprInstr (JSR reg addr n)
826 ptext SLIT("\tjsr\t"),
832 pprInstr (FUNBEGIN clab)
834 if (externallyVisibleCLabel clab) then
835 hcat [ptext SLIT("\t.globl\t"), pp_lab, char '\n']
838 ptext SLIT("\t.ent "),
847 pp_lab = pprCLabel_asm clab
849 -- NEVER use commas within those string literals, cpp will ruin your day
850 pp_ldgp = hcat [ ptext SLIT(":\n\tldgp $29"), char ',', ptext SLIT("0($27)\n") ]
851 pp_frame = hcat [ ptext SLIT("..ng:\n\t.frame $30"), char ',',
852 ptext SLIT("4240"), char ',',
853 ptext SLIT("$26"), char ',',
854 ptext SLIT("0\n\t.prologue 1") ]
856 pprInstr (FUNEND clab)
857 = (<>) (ptext SLIT("\t.align 4\n\t.end ")) (pprCLabel_asm clab)
860 Continue with Alpha-only printing bits and bobs:
864 pprRI (RIReg r) = pprReg r
865 pprRI (RIImm r) = pprImm r
867 pprRegRIReg :: FAST_STRING -> Reg -> RI -> Reg -> Doc
869 pprRegRIReg name reg1 ri reg2
881 pprSizeRegRegReg :: FAST_STRING -> Size -> Reg -> Reg -> Reg -> Doc
883 pprSizeRegRegReg name size reg1 reg2 reg3
896 #endif {-alpha_TARGET_ARCH-}
899 %************************************************************************
901 \subsubsection{@pprInstr@ for an I386}
903 %************************************************************************
908 pprInstr v@(MOV size s@(OpReg src) d@(OpReg dst)) -- hack
911 #if 0 /* #ifdef DEBUG */
912 (<>) (ptext SLIT("# warning: ")) (pprSizeOpOp SLIT("mov") size s d)
916 pprInstr (MOV size src dst)
917 = pprSizeOpOp SLIT("mov") size src dst
918 pprInstr (MOVZxL sizes src dst) = pprSizeOpOpCoerce SLIT("movz") sizes L src dst
919 pprInstr (MOVSxL sizes src dst) = pprSizeOpOpCoerce SLIT("movs") sizes L src dst
921 -- here we do some patching, since the physical registers are only set late
922 -- in the code generation.
923 pprInstr (LEA size (OpAddr (AddrBaseIndex src1@(Just reg1) (Just (reg2,1)) (ImmInt 0))) dst@(OpReg reg3))
925 = pprSizeOpOp SLIT("add") size (OpReg reg2) dst
926 pprInstr (LEA size (OpAddr (AddrBaseIndex src1@(Just reg1) (Just (reg2,1)) (ImmInt 0))) dst@(OpReg reg3))
928 = pprSizeOpOp SLIT("add") size (OpReg reg1) dst
929 pprInstr (LEA size (OpAddr (AddrBaseIndex src1@(Just reg1) Nothing displ)) dst@(OpReg reg3))
931 = pprInstr (ADD size (OpImm displ) dst)
932 pprInstr (LEA size src dst) = pprSizeOpOp SLIT("lea") size src dst
934 pprInstr (ADD size (OpImm (ImmInt (-1))) dst)
935 = pprSizeOp SLIT("dec") size dst
936 pprInstr (ADD size (OpImm (ImmInt 1)) dst)
937 = pprSizeOp SLIT("inc") size dst
938 pprInstr (ADD size src dst)
939 = pprSizeOpOp SLIT("add") size src dst
940 pprInstr (SUB size src dst) = pprSizeOpOp SLIT("sub") size src dst
941 pprInstr (IMUL size op1 op2) = pprSizeOpOp SLIT("imul") size op1 op2
943 {- A hack. The Intel documentation says that "The two and three
944 operand forms [of IMUL] may also be used with unsigned operands
945 because the lower half of the product is the same regardless if
946 (sic) the operands are signed or unsigned. The CF and OF flags,
947 however, cannot be used to determine if the upper half of the
948 result is non-zero." So there.
950 pprInstr (MUL size op1 op2) = pprSizeOpOp SLIT("imul") size op1 op2
952 pprInstr (AND size src dst) = pprSizeOpOp SLIT("and") size src dst
953 pprInstr (OR size src dst) = pprSizeOpOp SLIT("or") size src dst
954 pprInstr (XOR size src dst) = pprSizeOpOp SLIT("xor") size src dst
955 pprInstr (NOT size op) = pprSizeOp SLIT("not") size op
956 pprInstr (NEGI size op) = pprSizeOp SLIT("neg") size op
958 pprInstr (SHL size imm dst) = pprSizeImmOp SLIT("shl") size imm dst
959 pprInstr (SAR size imm dst) = pprSizeImmOp SLIT("sar") size imm dst
960 pprInstr (SHR size imm dst) = pprSizeImmOp SLIT("shr") size imm dst
961 pprInstr (BT size imm src) = pprSizeImmOp SLIT("bt") size imm src
963 pprInstr (CMP size src dst) = pprSizeOpOp SLIT("cmp") size src dst
964 pprInstr (TEST size src dst) = pprSizeOpOp SLIT("test") size src dst
965 pprInstr (PUSH size op) = pprSizeOp SLIT("push") size op
966 pprInstr (POP size op) = pprSizeOp SLIT("pop") size op
967 pprInstr PUSHA = ptext SLIT("\tpushal")
968 pprInstr POPA = ptext SLIT("\tpopal")
970 pprInstr (NOP) = ptext SLIT("\tnop")
971 pprInstr (CLTD) = ptext SLIT("\tcltd")
973 pprInstr (SETCC cond op) = pprCondInstr SLIT("set") cond (pprOperand B op)
975 pprInstr (JXX cond lab) = pprCondInstr SLIT("j") cond (pprCLabel_asm lab)
977 pprInstr (JMP dsts (OpImm imm)) = (<>) (ptext SLIT("\tjmp ")) (pprImm imm)
978 pprInstr (JMP dsts op) = (<>) (ptext SLIT("\tjmp *")) (pprOperand L op)
979 pprInstr (CALL imm) = (<>) (ptext SLIT("\tcall ")) (pprImm imm)
981 -- First bool indicates signedness; second whether quot or rem
982 pprInstr (IQUOT sz src dst) = pprInstr_quotRem True True sz src dst
983 pprInstr (IREM sz src dst) = pprInstr_quotRem True False sz src dst
985 pprInstr (QUOT sz src dst) = pprInstr_quotRem False True sz src dst
986 pprInstr (REM sz src dst) = pprInstr_quotRem False False sz src dst
988 -- Simulating a flat register set on the x86 FP stack is tricky.
989 -- you have to free %st(7) before pushing anything on the FP reg stack
990 -- so as to preclude the possibility of a FP stack overflow exception.
991 pprInstr g@(GMOV src dst)
995 = pprG g (hcat [gtab, gpush src 0, gsemi, gpop dst 1])
997 -- GLD sz addr dst ==> FFREE %st(7) ; FLDsz addr ; FSTP (dst+1)
998 pprInstr g@(GLD sz addr dst)
999 = pprG g (hcat [gtab, text "ffree %st(7) ; fld", pprSize sz, gsp,
1000 pprAddr addr, gsemi, gpop dst 1])
1002 -- GST sz src addr ==> FFREE %st(7) ; FLD dst ; FSTPsz addr
1003 pprInstr g@(GST sz src addr)
1004 = pprG g (hcat [gtab, gpush src 0, gsemi,
1005 text "fstp", pprSize sz, gsp, pprAddr addr])
1007 pprInstr g@(GLDZ dst)
1008 = pprG g (hcat [gtab, text "ffree %st(7) ; fldz ; ", gpop dst 1])
1009 pprInstr g@(GLD1 dst)
1010 = pprG g (hcat [gtab, text "ffree %st(7) ; fld1 ; ", gpop dst 1])
1012 pprInstr g@(GFTOI src dst)
1013 = pprInstr (GDTOI src dst)
1014 pprInstr g@(GDTOI src dst)
1015 = pprG g (hcat [gtab, text "subl $4, %esp ; ",
1016 gpush src 0, gsemi, text "fistpl 0(%esp) ; popl ",
1019 pprInstr g@(GITOF src dst)
1020 = pprInstr (GITOD src dst)
1021 pprInstr g@(GITOD src dst)
1022 = pprG g (hcat [gtab, text "pushl ", pprReg L src,
1023 text " ; ffree %st(7); fildl (%esp) ; ",
1024 gpop dst 1, text " ; addl $4,%esp"])
1026 pprInstr g@(GCMP sz src1 src2)
1027 = pprG g (hcat [gtab, text "pushl %eax ; ",gpush src1 0]
1029 hcat [gtab, text "fcomp ", greg src2 1,
1030 text "; fstsw %ax ; sahf ; popl %eax"])
1032 pprInstr g@(GABS sz src dst)
1033 = pprG g (hcat [gtab, gpush src 0, text " ; fabs ; ", gpop dst 1])
1034 pprInstr g@(GNEG sz src dst)
1035 = pprG g (hcat [gtab, gpush src 0, text " ; fchs ; ", gpop dst 1])
1037 pprInstr g@(GSQRT sz src dst)
1038 = pprG g (hcat [gtab, gpush src 0, text " ; fsqrt"] $$
1039 hcat [gtab, gcoerceto sz, gpop dst 1])
1040 pprInstr g@(GSIN sz src dst)
1041 = pprG g (hcat [gtab, gpush src 0, text " ; fsin"] $$
1042 hcat [gtab, gcoerceto sz, gpop dst 1])
1043 pprInstr g@(GCOS sz src dst)
1044 = pprG g (hcat [gtab, gpush src 0, text " ; fcos"] $$
1045 hcat [gtab, gcoerceto sz, gpop dst 1])
1046 pprInstr g@(GTAN sz src dst)
1047 = pprG g (hcat [gtab, text "ffree %st(6) ; ",
1048 gpush src 0, text " ; fptan ; ",
1049 text " fstp %st(0)"] $$
1050 hcat [gtab, gcoerceto sz, gpop dst 1])
1052 -- In the translations for GADD, GMUL, GSUB and GDIV,
1053 -- the first two cases are mere optimisations. The otherwise clause
1054 -- generates correct code under all circumstances.
1056 pprInstr g@(GADD sz src1 src2 dst)
1058 = pprG g (text "\t#GADD-xxxcase1" $$
1059 hcat [gtab, gpush src2 0,
1060 text " ; faddp %st(0),", greg src1 1])
1062 = pprG g (text "\t#GADD-xxxcase2" $$
1063 hcat [gtab, gpush src1 0,
1064 text " ; faddp %st(0),", greg src2 1])
1066 = pprG g (hcat [gtab, gpush src1 0,
1067 text " ; fadd ", greg src2 1, text ",%st(0)",
1071 pprInstr g@(GMUL sz src1 src2 dst)
1073 = pprG g (text "\t#GMUL-xxxcase1" $$
1074 hcat [gtab, gpush src2 0,
1075 text " ; fmulp %st(0),", greg src1 1])
1077 = pprG g (text "\t#GMUL-xxxcase2" $$
1078 hcat [gtab, gpush src1 0,
1079 text " ; fmulp %st(0),", greg src2 1])
1081 = pprG g (hcat [gtab, gpush src1 0,
1082 text " ; fmul ", greg src2 1, text ",%st(0)",
1086 pprInstr g@(GSUB sz src1 src2 dst)
1088 = pprG g (text "\t#GSUB-xxxcase1" $$
1089 hcat [gtab, gpush src2 0,
1090 text " ; fsubrp %st(0),", greg src1 1])
1092 = pprG g (text "\t#GSUB-xxxcase2" $$
1093 hcat [gtab, gpush src1 0,
1094 text " ; fsubp %st(0),", greg src2 1])
1096 = pprG g (hcat [gtab, gpush src1 0,
1097 text " ; fsub ", greg src2 1, text ",%st(0)",
1101 pprInstr g@(GDIV sz src1 src2 dst)
1103 = pprG g (text "\t#GDIV-xxxcase1" $$
1104 hcat [gtab, gpush src2 0,
1105 text " ; fdivrp %st(0),", greg src1 1])
1107 = pprG g (text "\t#GDIV-xxxcase2" $$
1108 hcat [gtab, gpush src1 0,
1109 text " ; fdivp %st(0),", greg src2 1])
1111 = pprG g (hcat [gtab, gpush src1 0,
1112 text " ; fdiv ", greg src2 1, text ",%st(0)",
1117 = vcat [ ptext SLIT("\tffree %st(0) ;ffree %st(1) ;ffree %st(2) ;ffree %st(3)"),
1118 ptext SLIT("\tffree %st(4) ;ffree %st(5) ;ffree %st(6) ;ffree %st(7)")
1122 pprInstr_quotRem signed isQuot sz src dst
1123 | case sz of L -> False; _ -> True
1124 = panic "pprInstr_quotRem: dunno how to do non-32bit operands"
1127 (text "\t# BEGIN " <> fakeInsn),
1128 (text "\tpushl $0; pushl %eax; pushl %edx; pushl " <> pprOperand sz src),
1129 (text "\tmovl " <> pprOperand sz dst <> text ",%eax; xorl %edx,%edx; cltd"),
1130 (x86op <> text " 0(%esp); movl " <> text resReg <> text ",12(%esp)"),
1131 (text "\tpopl %edx; popl %edx; popl %eax; popl " <> pprOperand sz dst),
1132 (text "\t# END " <> fakeInsn)
1135 x86op = if signed then text "\tidivl" else text "\tdivl"
1136 resReg = if isQuot then "%eax" else "%edx"
1137 opStr | signed = if isQuot then "IQUOT" else "IREM"
1138 | not signed = if isQuot then "QUOT" else "REM"
1139 fakeInsn = text opStr <+> pprOperand sz src
1140 <> char ',' <+> pprOperand sz dst
1142 --------------------------
1144 -- coerce %st(0) to the specified size
1145 gcoerceto DF = empty
1146 gcoerceto F = empty --text "subl $4,%esp ; fstps (%esp) ; flds (%esp) ; addl $4,%esp ; "
1149 = hcat [text "ffree %st(7) ; fld ", greg reg offset]
1151 = hcat [text "fstp ", greg reg offset]
1153 bogus = text "\tbogus"
1154 greg reg offset = text "%st(" <> int (gregno reg - 8+offset) <> char ')'
1159 gregno (RealReg i) = i
1160 gregno other = --pprPanic "gregno" (ppr other)
1161 999 -- bogus; only needed for debug printing
1163 pprG :: Instr -> Doc -> Doc
1165 = (char '#' <> pprGInstr fake) $$ actual
1167 pprGInstr (GMOV src dst) = pprSizeRegReg SLIT("gmov") DF src dst
1168 pprGInstr (GLD sz src dst) = pprSizeAddrReg SLIT("gld") sz src dst
1169 pprGInstr (GST sz src dst) = pprSizeRegAddr SLIT("gst") sz src dst
1171 pprGInstr (GLDZ dst) = pprSizeReg SLIT("gldz") DF dst
1172 pprGInstr (GLD1 dst) = pprSizeReg SLIT("gld1") DF dst
1174 pprGInstr (GFTOI src dst) = pprSizeSizeRegReg SLIT("gftoi") F L src dst
1175 pprGInstr (GDTOI src dst) = pprSizeSizeRegReg SLIT("gdtoi") DF L src dst
1177 pprGInstr (GITOF src dst) = pprSizeSizeRegReg SLIT("gitof") L F src dst
1178 pprGInstr (GITOD src dst) = pprSizeSizeRegReg SLIT("gitod") L DF src dst
1180 pprGInstr (GCMP sz src dst) = pprSizeRegReg SLIT("gcmp") sz src dst
1181 pprGInstr (GABS sz src dst) = pprSizeRegReg SLIT("gabs") sz src dst
1182 pprGInstr (GNEG sz src dst) = pprSizeRegReg SLIT("gneg") sz src dst
1183 pprGInstr (GSQRT sz src dst) = pprSizeRegReg SLIT("gsqrt") sz src dst
1184 pprGInstr (GSIN sz src dst) = pprSizeRegReg SLIT("gsin") sz src dst
1185 pprGInstr (GCOS sz src dst) = pprSizeRegReg SLIT("gcos") sz src dst
1186 pprGInstr (GTAN sz src dst) = pprSizeRegReg SLIT("gtan") sz src dst
1188 pprGInstr (GADD sz src1 src2 dst) = pprSizeRegRegReg SLIT("gadd") sz src1 src2 dst
1189 pprGInstr (GSUB sz src1 src2 dst) = pprSizeRegRegReg SLIT("gsub") sz src1 src2 dst
1190 pprGInstr (GMUL sz src1 src2 dst) = pprSizeRegRegReg SLIT("gmul") sz src1 src2 dst
1191 pprGInstr (GDIV sz src1 src2 dst) = pprSizeRegRegReg SLIT("gdiv") sz src1 src2 dst
1194 Continue with I386-only printing bits and bobs:
1196 pprDollImm :: Imm -> Doc
1198 pprDollImm i = ptext SLIT("$") <> pprImm i
1200 pprOperand :: Size -> Operand -> Doc
1201 pprOperand s (OpReg r) = pprReg s r
1202 pprOperand s (OpImm i) = pprDollImm i
1203 pprOperand s (OpAddr ea) = pprAddr ea
1205 pprSizeImmOp :: FAST_STRING -> Size -> Imm -> Operand -> Doc
1206 pprSizeImmOp name size imm op1
1218 pprSizeOp :: FAST_STRING -> Size -> Operand -> Doc
1219 pprSizeOp name size op1
1228 pprSizeOpOp :: FAST_STRING -> Size -> Operand -> Operand -> Doc
1229 pprSizeOpOp name size op1 op2
1235 pprOperand size op1,
1240 pprSizeByteOpOp :: FAST_STRING -> Size -> Operand -> Operand -> Doc
1241 pprSizeByteOpOp name size op1 op2
1252 pprSizeOpReg :: FAST_STRING -> Size -> Operand -> Reg -> Doc
1253 pprSizeOpReg name size op1 reg
1259 pprOperand size op1,
1264 pprSizeReg :: FAST_STRING -> Size -> Reg -> Doc
1265 pprSizeReg name size reg1
1274 pprSizeRegReg :: FAST_STRING -> Size -> Reg -> Reg -> Doc
1275 pprSizeRegReg name size reg1 reg2
1286 pprSizeSizeRegReg :: FAST_STRING -> Size -> Size -> Reg -> Reg -> Doc
1287 pprSizeSizeRegReg name size1 size2 reg1 reg2
1299 pprSizeRegRegReg :: FAST_STRING -> Size -> Reg -> Reg -> Reg -> Doc
1300 pprSizeRegRegReg name size reg1 reg2 reg3
1313 pprSizeAddr :: FAST_STRING -> Size -> MachRegsAddr -> Doc
1314 pprSizeAddr name size op
1323 pprSizeAddrReg :: FAST_STRING -> Size -> MachRegsAddr -> Reg -> Doc
1324 pprSizeAddrReg name size op dst
1335 pprSizeRegAddr :: FAST_STRING -> Size -> Reg -> MachRegsAddr -> Doc
1336 pprSizeRegAddr name size src op
1347 pprOpOp :: FAST_STRING -> Size -> Operand -> Operand -> Doc
1348 pprOpOp name size op1 op2
1352 pprOperand size op1,
1357 pprSizeOpOpCoerce :: FAST_STRING -> Size -> Size -> Operand -> Operand -> Doc
1358 pprSizeOpOpCoerce name size1 size2 op1 op2
1359 = hcat [ char '\t', ptext name, pprSize size1, pprSize size2, space,
1360 pprOperand size1 op1,
1362 pprOperand size2 op2
1365 pprCondInstr :: FAST_STRING -> Cond -> Doc -> Doc
1366 pprCondInstr name cond arg
1367 = hcat [ char '\t', ptext name, pprCond cond, space, arg]
1369 #endif {-i386_TARGET_ARCH-}
1372 %************************************************************************
1374 \subsubsection{@pprInstr@ for a SPARC}
1376 %************************************************************************
1379 #if sparc_TARGET_ARCH
1381 -- a clumsy hack for now, to handle possible double alignment problems
1383 -- even clumsier, to allow for RegReg regs that show when doing indexed
1384 -- reads (bytearrays).
1387 -- Translate to the following:
1390 -- ld [g1+4],%f(n+1)
1391 -- sub g1,g2,g1 -- to restore g1
1392 pprInstr (LD DF (AddrRegReg g1 g2) reg)
1394 hcat [ptext SLIT("\tadd\t"), pprReg g1,comma,pprReg g2,comma,pprReg g1],
1395 hcat [pp_ld_lbracket, pprReg g1, pp_rbracket_comma, pprReg reg],
1396 hcat [pp_ld_lbracket, pprReg g1, ptext SLIT("+4]"), comma, pprReg (fPair reg)],
1397 hcat [ptext SLIT("\tsub\t"), pprReg g1,comma,pprReg g2,comma,pprReg g1]
1402 -- ld [addr+4],%f(n+1)
1403 pprInstr (LD DF addr reg) | isJust off_addr
1405 hcat [pp_ld_lbracket, pprAddr addr, pp_rbracket_comma, pprReg reg],
1406 hcat [pp_ld_lbracket, pprAddr addr2, pp_rbracket_comma,pprReg (fPair reg)]
1409 off_addr = addrOffset addr 4
1410 addr2 = case off_addr of Just x -> x
1413 pprInstr (LD size addr reg)
1424 -- The same clumsy hack as above
1426 -- Translate to the following:
1429 -- st %f(n+1),[g1+4]
1430 -- sub g1,g2,g1 -- to restore g1
1431 pprInstr (ST DF reg (AddrRegReg g1 g2))
1433 hcat [ptext SLIT("\tadd\t"), pprReg g1,comma,pprReg g2,comma,pprReg g1],
1434 hcat [ptext SLIT("\tst\t"), pprReg reg, pp_comma_lbracket,
1436 hcat [ptext SLIT("\tst\t"), pprReg (fPair reg), pp_comma_lbracket,
1437 pprReg g1, ptext SLIT("+4]")],
1438 hcat [ptext SLIT("\tsub\t"), pprReg g1,comma,pprReg g2,comma,pprReg g1]
1443 -- st %f(n+1),[addr+4]
1444 pprInstr (ST DF reg addr) | isJust off_addr
1446 hcat [ptext SLIT("\tst\t"), pprReg reg, pp_comma_lbracket,
1447 pprAddr addr, rbrack],
1448 hcat [ptext SLIT("\tst\t"), pprReg (fPair reg), pp_comma_lbracket,
1449 pprAddr addr2, rbrack]
1452 off_addr = addrOffset addr 4
1453 addr2 = case off_addr of Just x -> x
1455 -- no distinction is made between signed and unsigned bytes on stores for the
1456 -- Sparc opcodes (at least I cannot see any, and gas is nagging me --SOF),
1457 -- so we call a special-purpose pprSize for ST..
1459 pprInstr (ST size reg addr)
1470 pprInstr (ADD x cc reg1 ri reg2)
1471 | not x && not cc && riZero ri
1472 = hcat [ ptext SLIT("\tmov\t"), pprReg reg1, comma, pprReg reg2 ]
1474 = pprRegRIReg (if x then SLIT("addx") else SLIT("add")) cc reg1 ri reg2
1476 pprInstr (SUB x cc reg1 ri reg2)
1477 | not x && cc && reg2 == g0
1478 = hcat [ ptext SLIT("\tcmp\t"), pprReg reg1, comma, pprRI ri ]
1479 | not x && not cc && riZero ri
1480 = hcat [ ptext SLIT("\tmov\t"), pprReg reg1, comma, pprReg reg2 ]
1482 = pprRegRIReg (if x then SLIT("subx") else SLIT("sub")) cc reg1 ri reg2
1484 pprInstr (AND b reg1 ri reg2) = pprRegRIReg SLIT("and") b reg1 ri reg2
1485 pprInstr (ANDN b reg1 ri reg2) = pprRegRIReg SLIT("andn") b reg1 ri reg2
1487 pprInstr (OR b reg1 ri reg2)
1488 | not b && reg1 == g0
1489 = hcat [ ptext SLIT("\tmov\t"), pprRI ri, comma, pprReg reg2 ]
1491 = pprRegRIReg SLIT("or") b reg1 ri reg2
1493 pprInstr (ORN b reg1 ri reg2) = pprRegRIReg SLIT("orn") b reg1 ri reg2
1495 pprInstr (XOR b reg1 ri reg2) = pprRegRIReg SLIT("xor") b reg1 ri reg2
1496 pprInstr (XNOR b reg1 ri reg2) = pprRegRIReg SLIT("xnor") b reg1 ri reg2
1498 pprInstr (SLL reg1 ri reg2) = pprRegRIReg SLIT("sll") False reg1 ri reg2
1499 pprInstr (SRL reg1 ri reg2) = pprRegRIReg SLIT("srl") False reg1 ri reg2
1500 pprInstr (SRA reg1 ri reg2) = pprRegRIReg SLIT("sra") False reg1 ri reg2
1502 pprInstr (SETHI imm reg)
1504 ptext SLIT("\tsethi\t"),
1510 pprInstr NOP = ptext SLIT("\tnop")
1512 pprInstr (FABS F reg1 reg2) = pprSizeRegReg SLIT("fabs") F reg1 reg2
1513 pprInstr (FABS DF reg1 reg2)
1514 = (<>) (pprSizeRegReg SLIT("fabs") F reg1 reg2)
1515 (if (reg1 == reg2) then empty
1516 else (<>) (char '\n')
1517 (pprSizeRegReg SLIT("fmov") F (fPair reg1) (fPair reg2)))
1519 pprInstr (FADD size reg1 reg2 reg3)
1520 = pprSizeRegRegReg SLIT("fadd") size reg1 reg2 reg3
1521 pprInstr (FCMP e size reg1 reg2)
1522 = pprSizeRegReg (if e then SLIT("fcmpe") else SLIT("fcmp")) size reg1 reg2
1523 pprInstr (FDIV size reg1 reg2 reg3)
1524 = pprSizeRegRegReg SLIT("fdiv") size reg1 reg2 reg3
1526 pprInstr (FMOV F reg1 reg2) = pprSizeRegReg SLIT("fmov") F reg1 reg2
1527 pprInstr (FMOV DF reg1 reg2)
1528 = (<>) (pprSizeRegReg SLIT("fmov") F reg1 reg2)
1529 (if (reg1 == reg2) then empty
1530 else (<>) (char '\n')
1531 (pprSizeRegReg SLIT("fmov") F (fPair reg1) (fPair reg2)))
1533 pprInstr (FMUL size reg1 reg2 reg3)
1534 = pprSizeRegRegReg SLIT("fmul") size reg1 reg2 reg3
1536 pprInstr (FNEG F reg1 reg2) = pprSizeRegReg SLIT("fneg") F reg1 reg2
1537 pprInstr (FNEG DF reg1 reg2)
1538 = (<>) (pprSizeRegReg SLIT("fneg") F reg1 reg2)
1539 (if (reg1 == reg2) then empty
1540 else (<>) (char '\n')
1541 (pprSizeRegReg SLIT("fmov") F (fPair reg1) (fPair reg2)))
1543 pprInstr (FSQRT size reg1 reg2) = pprSizeRegReg SLIT("fsqrt") size reg1 reg2
1544 pprInstr (FSUB size reg1 reg2 reg3) = pprSizeRegRegReg SLIT("fsub") size reg1 reg2 reg3
1545 pprInstr (FxTOy size1 size2 reg1 reg2)
1558 pprReg reg1, comma, pprReg reg2
1562 pprInstr (BI cond b lab)
1564 ptext SLIT("\tb"), pprCond cond,
1565 if b then pp_comma_a else empty,
1570 pprInstr (BF cond b lab)
1572 ptext SLIT("\tfb"), pprCond cond,
1573 if b then pp_comma_a else empty,
1578 pprInstr (JMP dsts addr) = (<>) (ptext SLIT("\tjmp\t")) (pprAddr addr)
1580 pprInstr (CALL imm n _)
1581 = hcat [ ptext SLIT("\tcall\t"), pprImm imm, comma, int n ]
1584 Continue with SPARC-only printing bits and bobs:
1587 pprRI (RIReg r) = pprReg r
1588 pprRI (RIImm r) = pprImm r
1590 pprSizeRegReg :: FAST_STRING -> Size -> Reg -> Reg -> Doc
1591 pprSizeRegReg name size reg1 reg2
1596 F -> ptext SLIT("s\t")
1597 DF -> ptext SLIT("d\t")),
1603 pprSizeRegRegReg :: FAST_STRING -> Size -> Reg -> Reg -> Reg -> Doc
1604 pprSizeRegRegReg name size reg1 reg2 reg3
1609 F -> ptext SLIT("s\t")
1610 DF -> ptext SLIT("d\t")),
1618 pprRegRIReg :: FAST_STRING -> Bool -> Reg -> RI -> Reg -> Doc
1619 pprRegRIReg name b reg1 ri reg2
1623 if b then ptext SLIT("cc\t") else char '\t',
1631 pprRIReg :: FAST_STRING -> Bool -> RI -> Reg -> Doc
1632 pprRIReg name b ri reg1
1636 if b then ptext SLIT("cc\t") else char '\t',
1642 pp_ld_lbracket = ptext SLIT("\tld\t[")
1643 pp_rbracket_comma = text "],"
1644 pp_comma_lbracket = text ",["
1645 pp_comma_a = text ",a"
1647 #endif {-sparc_TARGET_ARCH-}