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 )
33 asmSDoc d = Outputable.withPprStyleDoc (
34 Outputable.mkCodeStyle Outputable.AsmStyle) d
35 pprCLabel_asm l = asmSDoc (pprCLabel l)
38 %************************************************************************
40 \subsection{@pprReg@: print a @Reg@}
42 %************************************************************************
44 For x86, the way we print a register name depends
45 on which bit of it we care about. Yurgh.
47 pprUserReg :: Reg -> Doc
48 pprUserReg = pprReg IF_ARCH_i386(L,)
50 pprReg :: IF_ARCH_i386(Size ->,) Reg -> Doc
52 pprReg IF_ARCH_i386(s,) r
54 RealReg i -> ppr_reg_no IF_ARCH_i386(s,) i
55 VirtualRegI u -> text "%vI_" <> asmSDoc (pprVRegUnique u)
56 VirtualRegF u -> text "%vF_" <> asmSDoc (pprVRegUnique u)
59 ppr_reg_no :: Int -> Doc
62 0 -> SLIT("$0"); 1 -> SLIT("$1");
63 2 -> SLIT("$2"); 3 -> SLIT("$3");
64 4 -> SLIT("$4"); 5 -> SLIT("$5");
65 6 -> SLIT("$6"); 7 -> SLIT("$7");
66 8 -> SLIT("$8"); 9 -> SLIT("$9");
67 10 -> SLIT("$10"); 11 -> SLIT("$11");
68 12 -> SLIT("$12"); 13 -> SLIT("$13");
69 14 -> SLIT("$14"); 15 -> SLIT("$15");
70 16 -> SLIT("$16"); 17 -> SLIT("$17");
71 18 -> SLIT("$18"); 19 -> SLIT("$19");
72 20 -> SLIT("$20"); 21 -> SLIT("$21");
73 22 -> SLIT("$22"); 23 -> SLIT("$23");
74 24 -> SLIT("$24"); 25 -> SLIT("$25");
75 26 -> SLIT("$26"); 27 -> SLIT("$27");
76 28 -> SLIT("$28"); 29 -> SLIT("$29");
77 30 -> SLIT("$30"); 31 -> SLIT("$31");
78 32 -> SLIT("$f0"); 33 -> SLIT("$f1");
79 34 -> SLIT("$f2"); 35 -> SLIT("$f3");
80 36 -> SLIT("$f4"); 37 -> SLIT("$f5");
81 38 -> SLIT("$f6"); 39 -> SLIT("$f7");
82 40 -> SLIT("$f8"); 41 -> SLIT("$f9");
83 42 -> SLIT("$f10"); 43 -> SLIT("$f11");
84 44 -> SLIT("$f12"); 45 -> SLIT("$f13");
85 46 -> SLIT("$f14"); 47 -> SLIT("$f15");
86 48 -> SLIT("$f16"); 49 -> SLIT("$f17");
87 50 -> SLIT("$f18"); 51 -> SLIT("$f19");
88 52 -> SLIT("$f20"); 53 -> SLIT("$f21");
89 54 -> SLIT("$f22"); 55 -> SLIT("$f23");
90 56 -> SLIT("$f24"); 57 -> SLIT("$f25");
91 58 -> SLIT("$f26"); 59 -> SLIT("$f27");
92 60 -> SLIT("$f28"); 61 -> SLIT("$f29");
93 62 -> SLIT("$f30"); 63 -> SLIT("$f31");
94 _ -> SLIT("very naughty alpha register")
98 ppr_reg_no :: Size -> Int -> Doc
99 ppr_reg_no B = ppr_reg_byte
100 ppr_reg_no Bu = ppr_reg_byte
101 ppr_reg_no W = ppr_reg_word
102 ppr_reg_no Wu = ppr_reg_word
103 ppr_reg_no _ = ppr_reg_long
105 ppr_reg_byte i = ptext
107 0 -> SLIT("%al"); 1 -> SLIT("%bl");
108 2 -> SLIT("%cl"); 3 -> SLIT("%dl");
109 _ -> SLIT("very naughty I386 byte register")
112 ppr_reg_word i = ptext
114 0 -> SLIT("%ax"); 1 -> SLIT("%bx");
115 2 -> SLIT("%cx"); 3 -> SLIT("%dx");
116 4 -> SLIT("%si"); 5 -> SLIT("%di");
117 6 -> SLIT("%bp"); 7 -> SLIT("%sp");
118 _ -> SLIT("very naughty I386 word register")
121 ppr_reg_long i = ptext
123 0 -> SLIT("%eax"); 1 -> SLIT("%ebx");
124 2 -> SLIT("%ecx"); 3 -> SLIT("%edx");
125 4 -> SLIT("%esi"); 5 -> SLIT("%edi");
126 6 -> SLIT("%ebp"); 7 -> SLIT("%esp");
127 8 -> SLIT("%fake0"); 9 -> SLIT("%fake1");
128 10 -> SLIT("%fake2"); 11 -> SLIT("%fake3");
129 12 -> SLIT("%fake4"); 13 -> SLIT("%fake5");
130 _ -> SLIT("very naughty I386 register")
133 #if sparc_TARGET_ARCH
134 ppr_reg_no :: Int -> Doc
137 0 -> SLIT("%g0"); 1 -> SLIT("%g1");
138 2 -> SLIT("%g2"); 3 -> SLIT("%g3");
139 4 -> SLIT("%g4"); 5 -> SLIT("%g5");
140 6 -> SLIT("%g6"); 7 -> SLIT("%g7");
141 8 -> SLIT("%o0"); 9 -> SLIT("%o1");
142 10 -> SLIT("%o2"); 11 -> SLIT("%o3");
143 12 -> SLIT("%o4"); 13 -> SLIT("%o5");
144 14 -> SLIT("%o6"); 15 -> SLIT("%o7");
145 16 -> SLIT("%l0"); 17 -> SLIT("%l1");
146 18 -> SLIT("%l2"); 19 -> SLIT("%l3");
147 20 -> SLIT("%l4"); 21 -> SLIT("%l5");
148 22 -> SLIT("%l6"); 23 -> SLIT("%l7");
149 24 -> SLIT("%i0"); 25 -> SLIT("%i1");
150 26 -> SLIT("%i2"); 27 -> SLIT("%i3");
151 28 -> SLIT("%i4"); 29 -> SLIT("%i5");
152 30 -> SLIT("%i6"); 31 -> SLIT("%i7");
153 32 -> SLIT("%f0"); 33 -> SLIT("%f1");
154 34 -> SLIT("%f2"); 35 -> SLIT("%f3");
155 36 -> SLIT("%f4"); 37 -> SLIT("%f5");
156 38 -> SLIT("%f6"); 39 -> SLIT("%f7");
157 40 -> SLIT("%f8"); 41 -> SLIT("%f9");
158 42 -> SLIT("%f10"); 43 -> SLIT("%f11");
159 44 -> SLIT("%f12"); 45 -> SLIT("%f13");
160 46 -> SLIT("%f14"); 47 -> SLIT("%f15");
161 48 -> SLIT("%f16"); 49 -> SLIT("%f17");
162 50 -> SLIT("%f18"); 51 -> SLIT("%f19");
163 52 -> SLIT("%f20"); 53 -> SLIT("%f21");
164 54 -> SLIT("%f22"); 55 -> SLIT("%f23");
165 56 -> SLIT("%f24"); 57 -> SLIT("%f25");
166 58 -> SLIT("%f26"); 59 -> SLIT("%f27");
167 60 -> SLIT("%f28"); 61 -> SLIT("%f29");
168 62 -> SLIT("%f30"); 63 -> SLIT("%f31");
169 _ -> SLIT("very naughty sparc register")
174 %************************************************************************
176 \subsection{@pprSize@: print a @Size@}
178 %************************************************************************
181 pprSize :: Size -> Doc
183 pprSize x = ptext (case x of
184 #if alpha_TARGET_ARCH
187 -- W -> SLIT("w") UNUSED
188 -- Wu -> SLIT("wu") UNUSED
191 -- FF -> SLIT("f") UNUSED
192 -- DF -> SLIT("d") UNUSED
193 -- GF -> SLIT("g") UNUSED
194 -- SF -> SLIT("s") UNUSED
208 #if sparc_TARGET_ARCH
217 pprStSize :: Size -> Doc
218 pprStSize x = ptext (case x of
230 %************************************************************************
232 \subsection{@pprCond@: print a @Cond@}
234 %************************************************************************
237 pprCond :: Cond -> Doc
239 pprCond c = ptext (case c of {
240 #if alpha_TARGET_ARCH
251 GEU -> SLIT("ae"); LU -> SLIT("b");
252 EQQ -> SLIT("e"); GTT -> SLIT("g");
253 GE -> SLIT("ge"); GU -> SLIT("a");
254 LTT -> SLIT("l"); LE -> SLIT("le");
255 LEU -> SLIT("be"); NE -> SLIT("ne");
256 NEG -> SLIT("s"); POS -> SLIT("ns");
257 CARRY -> SLIT("c"); OFLO -> SLIT("o");
258 ALWAYS -> SLIT("mp") -- hack
260 #if sparc_TARGET_ARCH
261 ALWAYS -> SLIT(""); NEVER -> SLIT("n");
262 GEU -> SLIT("geu"); LU -> SLIT("lu");
263 EQQ -> SLIT("e"); GTT -> SLIT("g");
264 GE -> SLIT("ge"); GU -> SLIT("gu");
265 LTT -> SLIT("l"); LE -> SLIT("le");
266 LEU -> SLIT("leu"); NE -> SLIT("ne");
267 NEG -> SLIT("neg"); POS -> SLIT("pos");
268 VC -> SLIT("vc"); VS -> SLIT("vs")
273 %************************************************************************
275 \subsection{@pprImm@: print an @Imm@}
277 %************************************************************************
282 pprImm (ImmInt i) = int i
283 pprImm (ImmInteger i) = integer i
284 pprImm (ImmCLbl l) = (if labelDynamic l then text "__imp_" else empty)
286 pprImm (ImmIndex l i) = (if labelDynamic l then text "__imp_" else empty)
287 <> pprCLabel_asm l <> char '+' <> int i
288 pprImm (ImmLit s) = s
290 pprImm (ImmLab dll s) = (if underscorePrefix then char '_' else empty)
291 <> (if dll then text "_imp__" else empty)
294 #if sparc_TARGET_ARCH
296 = hcat [ pp_lo, pprImm i, rparen ]
301 = hcat [ pp_hi, pprImm i, rparen ]
307 %************************************************************************
309 \subsection{@pprAddr@: print an @Addr@}
311 %************************************************************************
314 pprAddr :: MachRegsAddr -> Doc
316 #if alpha_TARGET_ARCH
317 pprAddr (AddrReg r) = parens (pprReg r)
318 pprAddr (AddrImm i) = pprImm i
319 pprAddr (AddrRegImm r1 i)
320 = (<>) (pprImm i) (parens (pprReg r1))
326 pprAddr (ImmAddr imm off)
327 = let pp_imm = pprImm imm
331 else if (off < 0) then
334 pp_imm <> char '+' <> int off
336 pprAddr (AddrBaseIndex base index displacement)
338 pp_disp = ppr_disp displacement
339 pp_off p = pp_disp <> char '(' <> p <> char ')'
340 pp_reg r = pprReg L r
343 (Nothing, Nothing) -> pp_disp
344 (Just b, Nothing) -> pp_off (pp_reg b)
345 (Nothing, Just (r,i)) -> pp_off (pp_reg r <> comma <> int i)
346 (Just b, Just (r,i)) -> pp_off (pp_reg b <> comma <> pp_reg r
349 ppr_disp (ImmInt 0) = empty
350 ppr_disp imm = pprImm imm
355 #if sparc_TARGET_ARCH
356 pprAddr (AddrRegReg r1 (RealReg 0)) = pprReg r1
358 pprAddr (AddrRegReg r1 r2)
359 = hcat [ pprReg r1, char '+', pprReg r2 ]
361 pprAddr (AddrRegImm r1 (ImmInt i))
363 | not (fits13Bits i) = largeOffsetError i
364 | otherwise = hcat [ pprReg r1, pp_sign, int i ]
366 pp_sign = if i > 0 then char '+' else empty
368 pprAddr (AddrRegImm r1 (ImmInteger i))
370 | not (fits13Bits i) = largeOffsetError i
371 | otherwise = hcat [ pprReg r1, pp_sign, integer i ]
373 pp_sign = if i > 0 then char '+' else empty
375 pprAddr (AddrRegImm r1 imm)
376 = hcat [ pprReg r1, char '+', pprImm imm ]
380 %************************************************************************
382 \subsection{@pprInstr@: print an @Instr@}
384 %************************************************************************
387 pprInstr :: Instr -> Doc
389 --pprInstr (COMMENT s) = empty -- nuke 'em
391 = IF_ARCH_alpha( ((<>) (ptext SLIT("\t# ")) (ftext s))
392 ,IF_ARCH_sparc( ((<>) (ptext SLIT("! ")) (ftext s))
393 ,IF_ARCH_i386( ((<>) (ptext SLIT("# ")) (ftext s))
397 = pprInstr (COMMENT (mkFastString ("\tdelta = " ++ show d)))
399 pprInstr (SEGMENT TextSegment)
400 = IF_ARCH_alpha(ptext SLIT("\t.text\n\t.align 3") {-word boundary-}
401 ,IF_ARCH_sparc(ptext SLIT(".text\n\t.align 4") {-word boundary-}
402 ,IF_ARCH_i386((text ".text\n\t.align 4,0x90") {-needs per-OS variation!-}
405 pprInstr (SEGMENT DataSegment)
407 IF_ARCH_alpha(SLIT("\t.data\n\t.align 3")
408 ,IF_ARCH_sparc(SLIT(".data\n\t.align 8") {-<8 will break double constants -}
409 ,IF_ARCH_i386(SLIT(".data\n\t.align 4")
412 pprInstr (SEGMENT RoDataSegment)
414 IF_ARCH_alpha(SLIT("\t.data\n\t.align 3")
415 ,IF_ARCH_sparc(SLIT(".data\n\t.align 8") {-<8 will break double constants -}
416 ,IF_ARCH_i386(SLIT(".section .rodata\n\t.align 4")
419 pprInstr (LABEL clab)
421 pp_lab = pprCLabel_asm clab
424 if not (externallyVisibleCLabel clab) then
428 IF_ARCH_alpha(SLIT("\t.globl\t")
429 ,IF_ARCH_i386(SLIT(".globl ")
430 ,IF_ARCH_sparc(SLIT(".global\t")
432 , pp_lab, char '\n'],
437 pprInstr (ASCII False{-no backslash conversion-} str)
438 = hcat [ ptext SLIT("\t.asciz "), char '\"', text str, char '"' ]
440 pprInstr (ASCII True str)
441 = vcat (map do1 (str ++ [chr 0]))
444 do1 c = ptext SLIT("\t.byte\t0x") <> hshow (ord c)
447 hshow n | n >= 0 && n <= 255
448 = char (tab !! (n `div` 16)) <> char (tab !! (n `mod` 16))
449 tab = "0123456789ABCDEF"
453 = vcat (concatMap (ppr_item s) xs)
456 #if alpha_TARGET_ARCH
457 ppr_item = error "ppr_item on Alpha"
459 #if sparc_TARGET_ARCH
460 -- copy n paste of x86 version
461 ppr_item B x = [ptext SLIT("\t.byte\t") <> pprImm x]
462 ppr_item W x = [ptext SLIT("\t.long\t") <> pprImm x]
463 ppr_item F (ImmFloat r)
464 = let bs = floatToBytes (fromRational r)
465 in map (\b -> ptext SLIT("\t.byte\t") <> pprImm (ImmInt b)) bs
466 ppr_item DF (ImmDouble r)
467 = let bs = doubleToBytes (fromRational r)
468 in map (\b -> ptext SLIT("\t.byte\t") <> pprImm (ImmInt b)) bs
471 ppr_item B x = [ptext SLIT("\t.byte\t") <> pprImm x]
472 ppr_item L x = [ptext SLIT("\t.long\t") <> pprImm x]
473 ppr_item F (ImmFloat r)
474 = let bs = floatToBytes (fromRational r)
475 in map (\b -> ptext SLIT("\t.byte\t") <> pprImm (ImmInt b)) bs
476 ppr_item DF (ImmDouble r)
477 = let bs = doubleToBytes (fromRational r)
478 in map (\b -> ptext SLIT("\t.byte\t") <> pprImm (ImmInt b)) bs
481 -- floatToBytes and doubleToBytes convert to the host's byte
482 -- order. Providing that we're not cross-compiling for a
483 -- target with the opposite endianness, this should work ok
485 floatToBytes :: Float -> [Int]
488 arr <- newFloatArray ((0::Int),3)
489 writeFloatArray arr 0 f
490 i0 <- readCharArray arr 0
491 i1 <- readCharArray arr 1
492 i2 <- readCharArray arr 2
493 i3 <- readCharArray arr 3
494 return (map ord [i0,i1,i2,i3])
497 doubleToBytes :: Double -> [Int]
500 arr <- newDoubleArray ((0::Int),7)
501 writeDoubleArray arr 0 d
502 i0 <- readCharArray arr 0
503 i1 <- readCharArray arr 1
504 i2 <- readCharArray arr 2
505 i3 <- readCharArray arr 3
506 i4 <- readCharArray arr 4
507 i5 <- readCharArray arr 5
508 i6 <- readCharArray arr 6
509 i7 <- readCharArray arr 7
510 return (map ord [i0,i1,i2,i3,i4,i5,i6,i7])
513 -- fall through to rest of (machine-specific) pprInstr...
516 %************************************************************************
518 \subsubsection{@pprInstr@ for an Alpha}
520 %************************************************************************
523 #if alpha_TARGET_ARCH
525 pprInstr (LD size reg addr)
535 pprInstr (LDA reg addr)
537 ptext SLIT("\tlda\t"),
543 pprInstr (LDAH reg addr)
545 ptext SLIT("\tldah\t"),
551 pprInstr (LDGP reg addr)
553 ptext SLIT("\tldgp\t"),
559 pprInstr (LDI size reg imm)
569 pprInstr (ST size reg addr)
581 ptext SLIT("\tclr\t"),
585 pprInstr (ABS size ri reg)
595 pprInstr (NEG size ov ri reg)
599 if ov then ptext SLIT("v\t") else char '\t',
605 pprInstr (ADD size ov reg1 ri reg2)
609 if ov then ptext SLIT("v\t") else char '\t',
617 pprInstr (SADD size scale reg1 ri reg2)
619 ptext (case scale of {{-UNUSED:L -> SLIT("\ts4");-} Q -> SLIT("\ts8")}),
630 pprInstr (SUB size ov reg1 ri reg2)
634 if ov then ptext SLIT("v\t") else char '\t',
642 pprInstr (SSUB size scale reg1 ri reg2)
644 ptext (case scale of {{-UNUSED:L -> SLIT("\ts4");-} Q -> SLIT("\ts8")}),
655 pprInstr (MUL size ov reg1 ri reg2)
659 if ov then ptext SLIT("v\t") else char '\t',
667 pprInstr (DIV size uns reg1 ri reg2)
671 if uns then ptext SLIT("u\t") else char '\t',
679 pprInstr (REM size uns reg1 ri reg2)
683 if uns then ptext SLIT("u\t") else char '\t',
691 pprInstr (NOT ri reg)
700 pprInstr (AND reg1 ri reg2) = pprRegRIReg SLIT("and") reg1 ri reg2
701 pprInstr (ANDNOT reg1 ri reg2) = pprRegRIReg SLIT("andnot") reg1 ri reg2
702 pprInstr (OR reg1 ri reg2) = pprRegRIReg SLIT("or") reg1 ri reg2
703 pprInstr (ORNOT reg1 ri reg2) = pprRegRIReg SLIT("ornot") reg1 ri reg2
704 pprInstr (XOR reg1 ri reg2) = pprRegRIReg SLIT("xor") reg1 ri reg2
705 pprInstr (XORNOT reg1 ri reg2) = pprRegRIReg SLIT("xornot") reg1 ri reg2
707 pprInstr (SLL reg1 ri reg2) = pprRegRIReg SLIT("sll") reg1 ri reg2
708 pprInstr (SRL reg1 ri reg2) = pprRegRIReg SLIT("srl") reg1 ri reg2
709 pprInstr (SRA reg1 ri reg2) = pprRegRIReg SLIT("sra") reg1 ri reg2
711 pprInstr (ZAP reg1 ri reg2) = pprRegRIReg SLIT("zap") reg1 ri reg2
712 pprInstr (ZAPNOT reg1 ri reg2) = pprRegRIReg SLIT("zapnot") reg1 ri reg2
714 pprInstr (NOP) = ptext SLIT("\tnop")
716 pprInstr (CMP cond reg1 ri reg2)
730 ptext SLIT("\tfclr\t"),
734 pprInstr (FABS reg1 reg2)
736 ptext SLIT("\tfabs\t"),
742 pprInstr (FNEG size reg1 reg2)
752 pprInstr (FADD size reg1 reg2 reg3) = pprSizeRegRegReg SLIT("add") size reg1 reg2 reg3
753 pprInstr (FDIV size reg1 reg2 reg3) = pprSizeRegRegReg SLIT("div") size reg1 reg2 reg3
754 pprInstr (FMUL size reg1 reg2 reg3) = pprSizeRegRegReg SLIT("mul") size reg1 reg2 reg3
755 pprInstr (FSUB size reg1 reg2 reg3) = pprSizeRegRegReg SLIT("sub") size reg1 reg2 reg3
757 pprInstr (CVTxy size1 size2 reg1 reg2)
761 case size2 of {Q -> ptext SLIT("qc"); _ -> pprSize size2},
768 pprInstr (FCMP size cond reg1 reg2 reg3)
781 pprInstr (FMOV reg1 reg2)
783 ptext SLIT("\tfmov\t"),
789 pprInstr (BI ALWAYS reg lab) = pprInstr (BR lab)
791 pprInstr (BI NEVER reg lab) = empty
793 pprInstr (BI cond reg lab)
803 pprInstr (BF cond reg lab)
814 = (<>) (ptext SLIT("\tbr\t")) (pprImm lab)
816 pprInstr (JMP reg addr hint)
818 ptext SLIT("\tjmp\t"),
827 = (<>) (ptext SLIT("\tbsr\t")) (pprImm imm)
829 pprInstr (JSR reg addr n)
831 ptext SLIT("\tjsr\t"),
837 pprInstr (FUNBEGIN clab)
839 if (externallyVisibleCLabel clab) then
840 hcat [ptext SLIT("\t.globl\t"), pp_lab, char '\n']
843 ptext SLIT("\t.ent "),
852 pp_lab = pprCLabel_asm clab
854 -- NEVER use commas within those string literals, cpp will ruin your day
855 pp_ldgp = hcat [ ptext SLIT(":\n\tldgp $29"), char ',', ptext SLIT("0($27)\n") ]
856 pp_frame = hcat [ ptext SLIT("..ng:\n\t.frame $30"), char ',',
857 ptext SLIT("4240"), char ',',
858 ptext SLIT("$26"), char ',',
859 ptext SLIT("0\n\t.prologue 1") ]
861 pprInstr (FUNEND clab)
862 = (<>) (ptext SLIT("\t.align 4\n\t.end ")) (pprCLabel_asm clab)
865 Continue with Alpha-only printing bits and bobs:
869 pprRI (RIReg r) = pprReg r
870 pprRI (RIImm r) = pprImm r
872 pprRegRIReg :: LitString -> Reg -> RI -> Reg -> Doc
873 pprRegRIReg name reg1 ri reg2
885 pprSizeRegRegReg :: LitString -> Size -> Reg -> Reg -> Reg -> Doc
886 pprSizeRegRegReg name size reg1 reg2 reg3
899 #endif {-alpha_TARGET_ARCH-}
902 %************************************************************************
904 \subsubsection{@pprInstr@ for an I386}
906 %************************************************************************
911 pprInstr v@(MOV size s@(OpReg src) d@(OpReg dst)) -- hack
914 #if 0 /* #ifdef DEBUG */
915 (<>) (ptext SLIT("# warning: ")) (pprSizeOpOp SLIT("mov") size s d)
919 pprInstr (MOV size src dst)
920 = pprSizeOpOp SLIT("mov") size src dst
921 pprInstr (MOVZxL sizes src dst) = pprSizeOpOpCoerce SLIT("movz") sizes L src dst
922 pprInstr (MOVSxL sizes src dst) = pprSizeOpOpCoerce SLIT("movs") sizes L src dst
924 -- here we do some patching, since the physical registers are only set late
925 -- in the code generation.
926 pprInstr (LEA size (OpAddr (AddrBaseIndex src1@(Just reg1) (Just (reg2,1)) (ImmInt 0))) dst@(OpReg reg3))
928 = pprSizeOpOp SLIT("add") size (OpReg reg2) dst
929 pprInstr (LEA size (OpAddr (AddrBaseIndex src1@(Just reg1) (Just (reg2,1)) (ImmInt 0))) dst@(OpReg reg3))
931 = pprSizeOpOp SLIT("add") size (OpReg reg1) dst
932 pprInstr (LEA size (OpAddr (AddrBaseIndex src1@(Just reg1) Nothing displ)) dst@(OpReg reg3))
934 = pprInstr (ADD size (OpImm displ) dst)
935 pprInstr (LEA size src dst) = pprSizeOpOp SLIT("lea") size src dst
937 pprInstr (ADD size (OpImm (ImmInt (-1))) dst)
938 = pprSizeOp SLIT("dec") size dst
939 pprInstr (ADD size (OpImm (ImmInt 1)) dst)
940 = pprSizeOp SLIT("inc") size dst
941 pprInstr (ADD size src dst)
942 = pprSizeOpOp SLIT("add") size src dst
943 pprInstr (SUB size src dst) = pprSizeOpOp SLIT("sub") size src dst
944 pprInstr (IMUL size op1 op2) = pprSizeOpOp SLIT("imul") size op1 op2
946 {- A hack. The Intel documentation says that "The two and three
947 operand forms [of IMUL] may also be used with unsigned operands
948 because the lower half of the product is the same regardless if
949 (sic) the operands are signed or unsigned. The CF and OF flags,
950 however, cannot be used to determine if the upper half of the
951 result is non-zero." So there.
953 pprInstr (MUL size op1 op2) = pprSizeOpOp SLIT("imul") size op1 op2
955 pprInstr (AND size src dst) = pprSizeOpOp SLIT("and") size src dst
956 pprInstr (OR size src dst) = pprSizeOpOp SLIT("or") size src dst
957 pprInstr (XOR size src dst) = pprSizeOpOp SLIT("xor") size src dst
958 pprInstr (NOT size op) = pprSizeOp SLIT("not") size op
959 pprInstr (NEGI size op) = pprSizeOp SLIT("neg") size op
961 pprInstr (SHL size imm dst) = pprSizeImmOp SLIT("shl") size imm dst
962 pprInstr (SAR size imm dst) = pprSizeImmOp SLIT("sar") size imm dst
963 pprInstr (SHR size imm dst) = pprSizeImmOp SLIT("shr") size imm dst
964 pprInstr (BT size imm src) = pprSizeImmOp SLIT("bt") size imm src
966 pprInstr (CMP size src dst) = pprSizeOpOp SLIT("cmp") size src dst
967 pprInstr (TEST size src dst) = pprSizeOpOp SLIT("test") size src dst
968 pprInstr (PUSH size op) = pprSizeOp SLIT("push") size op
969 pprInstr (POP size op) = pprSizeOp SLIT("pop") size op
970 pprInstr PUSHA = ptext SLIT("\tpushal")
971 pprInstr POPA = ptext SLIT("\tpopal")
973 pprInstr NOP = ptext SLIT("\tnop")
974 pprInstr CLTD = ptext SLIT("\tcltd")
976 pprInstr (SETCC cond op) = pprCondInstr SLIT("set") cond (pprOperand B op)
978 pprInstr (JXX cond lab) = pprCondInstr SLIT("j") cond (pprCLabel_asm lab)
980 pprInstr (JMP dsts (OpImm imm)) = (<>) (ptext SLIT("\tjmp ")) (pprImm imm)
981 pprInstr (JMP dsts op) = (<>) (ptext SLIT("\tjmp *")) (pprOperand L op)
982 pprInstr (CALL (Left imm)) = (<>) (ptext SLIT("\tcall ")) (pprImm imm)
983 pprInstr (CALL (Right reg)) = (<>) (ptext SLIT("\tcall *")) (pprReg L reg)
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 {- Gruesome swamp follows. If you're unfortunate enough to have ventured
1034 this far into the jungle AND you give a Rat's Ass (tm) what's going
1035 on, here's the deal. Generate code to do a floating point comparison
1036 of src1 and src2, of kind cond, and set the Zero flag if true.
1038 The complications are to do with handling NaNs correctly. We want the
1039 property that if either argument is NaN, then the result of the
1040 comparison is False ... except if we're comparing for inequality,
1041 in which case the answer is True.
1043 Here's how the general (non-inequality) case works. As an
1044 example, consider generating the an equality test:
1046 pushl %eax -- we need to mess with this
1047 <get src1 to top of FPU stack>
1048 fcomp <src2 location in FPU stack> and pop pushed src1
1049 -- Result of comparison is in FPU Status Register bits
1051 fstsw %ax -- Move FPU Status Reg to %ax
1052 sahf -- move C3 C2 C0 from %ax to integer flag reg
1053 -- now the serious magic begins
1054 setpo %ah -- %ah = if comparable(neither arg was NaN) then 1 else 0
1055 sete %al -- %al = if arg1 == arg2 then 1 else 0
1056 andb %ah,%al -- %al &= %ah
1057 -- so %al == 1 iff (comparable && same); else it holds 0
1058 decb %al -- %al == 0, ZeroFlag=1 iff (comparable && same);
1059 else %al == 0xFF, ZeroFlag=0
1060 -- the zero flag is now set as we desire.
1063 The special case of inequality differs thusly:
1065 setpe %ah -- %ah = if incomparable(either arg was NaN) then 1 else 0
1066 setne %al -- %al = if arg1 /= arg2 then 1 else 0
1067 orb %ah,%al -- %al = if (incomparable || different) then 1 else 0
1068 decb %al -- if (incomparable || different) then (%al == 0, ZF=1)
1069 else (%al == 0xFF, ZF=0)
1071 pprInstr g@(GCMP cond src1 src2)
1072 | case cond of { NE -> True; other -> False }
1074 hcat [gtab, text "pushl %eax ; ",gpush src1 0],
1075 hcat [gtab, text "fcomp ", greg src2 1,
1076 text "; fstsw %ax ; sahf ; setpe %ah"],
1077 hcat [gtab, text "setne %al ; ",
1078 text "orb %ah,%al ; decb %al ; popl %eax"]
1082 hcat [gtab, text "pushl %eax ; ",gpush src1 0],
1083 hcat [gtab, text "fcomp ", greg src2 1,
1084 text "; fstsw %ax ; sahf ; setpo %ah"],
1085 hcat [gtab, text "set", pprCond (fix_FP_cond cond), text " %al ; ",
1086 text "andb %ah,%al ; decb %al ; popl %eax"]
1089 {- On the 486, the flags set by FP compare are the unsigned ones!
1090 (This looks like a HACK to me. WDP 96/03)
1092 fix_FP_cond :: Cond -> Cond
1093 fix_FP_cond GE = GEU
1094 fix_FP_cond GTT = GU
1095 fix_FP_cond LTT = LU
1096 fix_FP_cond LE = LEU
1097 fix_FP_cond EQQ = EQQ
1099 -- there should be no others
1102 pprInstr g@(GABS sz src dst)
1103 = pprG g (hcat [gtab, gpush src 0, text " ; fabs ; ", gpop dst 1])
1104 pprInstr g@(GNEG sz src dst)
1105 = pprG g (hcat [gtab, gpush src 0, text " ; fchs ; ", gpop dst 1])
1107 pprInstr g@(GSQRT sz src dst)
1108 = pprG g (hcat [gtab, gpush src 0, text " ; fsqrt"] $$
1109 hcat [gtab, gcoerceto sz, gpop dst 1])
1110 pprInstr g@(GSIN sz src dst)
1111 = pprG g (hcat [gtab, gpush src 0, text " ; fsin"] $$
1112 hcat [gtab, gcoerceto sz, gpop dst 1])
1113 pprInstr g@(GCOS sz src dst)
1114 = pprG g (hcat [gtab, gpush src 0, text " ; fcos"] $$
1115 hcat [gtab, gcoerceto sz, gpop dst 1])
1116 pprInstr g@(GTAN sz src dst)
1117 = pprG g (hcat [gtab, text "ffree %st(6) ; ",
1118 gpush src 0, text " ; fptan ; ",
1119 text " fstp %st(0)"] $$
1120 hcat [gtab, gcoerceto sz, gpop dst 1])
1122 -- In the translations for GADD, GMUL, GSUB and GDIV,
1123 -- the first two cases are mere optimisations. The otherwise clause
1124 -- generates correct code under all circumstances.
1126 pprInstr g@(GADD sz src1 src2 dst)
1128 = pprG g (text "\t#GADD-xxxcase1" $$
1129 hcat [gtab, gpush src2 0,
1130 text " ; faddp %st(0),", greg src1 1])
1132 = pprG g (text "\t#GADD-xxxcase2" $$
1133 hcat [gtab, gpush src1 0,
1134 text " ; faddp %st(0),", greg src2 1])
1136 = pprG g (hcat [gtab, gpush src1 0,
1137 text " ; fadd ", greg src2 1, text ",%st(0)",
1141 pprInstr g@(GMUL sz src1 src2 dst)
1143 = pprG g (text "\t#GMUL-xxxcase1" $$
1144 hcat [gtab, gpush src2 0,
1145 text " ; fmulp %st(0),", greg src1 1])
1147 = pprG g (text "\t#GMUL-xxxcase2" $$
1148 hcat [gtab, gpush src1 0,
1149 text " ; fmulp %st(0),", greg src2 1])
1151 = pprG g (hcat [gtab, gpush src1 0,
1152 text " ; fmul ", greg src2 1, text ",%st(0)",
1156 pprInstr g@(GSUB sz src1 src2 dst)
1158 = pprG g (text "\t#GSUB-xxxcase1" $$
1159 hcat [gtab, gpush src2 0,
1160 text " ; fsubrp %st(0),", greg src1 1])
1162 = pprG g (text "\t#GSUB-xxxcase2" $$
1163 hcat [gtab, gpush src1 0,
1164 text " ; fsubp %st(0),", greg src2 1])
1166 = pprG g (hcat [gtab, gpush src1 0,
1167 text " ; fsub ", greg src2 1, text ",%st(0)",
1171 pprInstr g@(GDIV sz src1 src2 dst)
1173 = pprG g (text "\t#GDIV-xxxcase1" $$
1174 hcat [gtab, gpush src2 0,
1175 text " ; fdivrp %st(0),", greg src1 1])
1177 = pprG g (text "\t#GDIV-xxxcase2" $$
1178 hcat [gtab, gpush src1 0,
1179 text " ; fdivp %st(0),", greg src2 1])
1181 = pprG g (hcat [gtab, gpush src1 0,
1182 text " ; fdiv ", greg src2 1, text ",%st(0)",
1187 = vcat [ ptext SLIT("\tffree %st(0) ;ffree %st(1) ;ffree %st(2) ;ffree %st(3)"),
1188 ptext SLIT("\tffree %st(4) ;ffree %st(5) ;ffree %st(6) ;ffree %st(7)")
1192 pprInstr_quotRem signed isQuot sz src dst
1193 | case sz of L -> False; _ -> True
1194 = panic "pprInstr_quotRem: dunno how to do non-32bit operands"
1197 (text "\t# BEGIN " <> fakeInsn),
1198 (text "\tpushl $0; pushl %eax; pushl %edx; pushl " <> pprOperand sz src),
1199 (text "\tmovl " <> pprOperand sz dst <> text ",%eax; " <> widen_to_64),
1200 (x86op <> text " 0(%esp); movl " <> text resReg <> text ",12(%esp)"),
1201 (text "\tpopl %edx; popl %edx; popl %eax; popl " <> pprOperand sz dst),
1202 (text "\t# END " <> fakeInsn)
1205 widen_to_64 | signed = text "cltd"
1206 | not signed = text "xorl %edx,%edx"
1207 x86op = if signed then text "\tidivl" else text "\tdivl"
1208 resReg = if isQuot then "%eax" else "%edx"
1209 opStr | signed = if isQuot then "IQUOT" else "IREM"
1210 | not signed = if isQuot then "QUOT" else "REM"
1211 fakeInsn = text opStr <+> pprOperand sz src
1212 <> char ',' <+> pprOperand sz dst
1214 -- Emit code to make hi_reg:lo_reg be the 64-bit product of hi_reg and lo_reg
1215 pprInstr_imul64 hi_reg lo_reg
1216 = let fakeInsn = text "imul64" <+> pp_hi_reg <> comma <+> pp_lo_reg
1217 pp_hi_reg = pprReg L hi_reg
1218 pp_lo_reg = pprReg L lo_reg
1221 text "\t# BEGIN " <> fakeInsn,
1222 text "\tpushl" <+> pp_hi_reg <> text" ; pushl" <+> pp_lo_reg,
1223 text "\tpushl %eax ; pushl %edx",
1224 text "\tmovl 12(%esp), %eax ; imull 8(%esp)",
1225 text "\tmovl %edx, 12(%esp) ; movl %eax, 8(%esp)",
1226 text "\tpopl %edx ; popl %eax",
1227 text "\tpopl" <+> pp_lo_reg <> text " ; popl" <+> pp_hi_reg,
1228 text "\t# END " <> fakeInsn
1232 --------------------------
1234 -- coerce %st(0) to the specified size
1235 gcoerceto DF = empty
1236 gcoerceto F = empty --text "subl $4,%esp ; fstps (%esp) ; flds (%esp) ; addl $4,%esp ; "
1239 = hcat [text "ffree %st(7) ; fld ", greg reg offset]
1241 = hcat [text "fstp ", greg reg offset]
1243 bogus = text "\tbogus"
1244 greg reg offset = text "%st(" <> int (gregno reg - 8+offset) <> char ')'
1249 gregno (RealReg i) = i
1250 gregno other = --pprPanic "gregno" (ppr other)
1251 999 -- bogus; only needed for debug printing
1253 pprG :: Instr -> Doc -> Doc
1255 = (char '#' <> pprGInstr fake) $$ actual
1257 pprGInstr (GMOV src dst) = pprSizeRegReg SLIT("gmov") DF src dst
1258 pprGInstr (GLD sz src dst) = pprSizeAddrReg SLIT("gld") sz src dst
1259 pprGInstr (GST sz src dst) = pprSizeRegAddr SLIT("gst") sz src dst
1261 pprGInstr (GLDZ dst) = pprSizeReg SLIT("gldz") DF dst
1262 pprGInstr (GLD1 dst) = pprSizeReg SLIT("gld1") DF dst
1264 pprGInstr (GFTOI src dst) = pprSizeSizeRegReg SLIT("gftoi") F L src dst
1265 pprGInstr (GDTOI src dst) = pprSizeSizeRegReg SLIT("gdtoi") DF L src dst
1267 pprGInstr (GITOF src dst) = pprSizeSizeRegReg SLIT("gitof") L F src dst
1268 pprGInstr (GITOD src dst) = pprSizeSizeRegReg SLIT("gitod") L DF src dst
1270 pprGInstr (GCMP co src dst) = pprCondRegReg SLIT("gcmp_") DF co src dst
1271 pprGInstr (GABS sz src dst) = pprSizeRegReg SLIT("gabs") sz src dst
1272 pprGInstr (GNEG sz src dst) = pprSizeRegReg SLIT("gneg") sz src dst
1273 pprGInstr (GSQRT sz src dst) = pprSizeRegReg SLIT("gsqrt") sz src dst
1274 pprGInstr (GSIN sz src dst) = pprSizeRegReg SLIT("gsin") sz src dst
1275 pprGInstr (GCOS sz src dst) = pprSizeRegReg SLIT("gcos") sz src dst
1276 pprGInstr (GTAN sz src dst) = pprSizeRegReg SLIT("gtan") sz src dst
1278 pprGInstr (GADD sz src1 src2 dst) = pprSizeRegRegReg SLIT("gadd") sz src1 src2 dst
1279 pprGInstr (GSUB sz src1 src2 dst) = pprSizeRegRegReg SLIT("gsub") sz src1 src2 dst
1280 pprGInstr (GMUL sz src1 src2 dst) = pprSizeRegRegReg SLIT("gmul") sz src1 src2 dst
1281 pprGInstr (GDIV sz src1 src2 dst) = pprSizeRegRegReg SLIT("gdiv") sz src1 src2 dst
1284 Continue with I386-only printing bits and bobs:
1286 pprDollImm :: Imm -> Doc
1288 pprDollImm i = ptext SLIT("$") <> pprImm i
1290 pprOperand :: Size -> Operand -> Doc
1291 pprOperand s (OpReg r) = pprReg s r
1292 pprOperand s (OpImm i) = pprDollImm i
1293 pprOperand s (OpAddr ea) = pprAddr ea
1295 pprSizeImmOp :: LitString -> Size -> Imm -> Operand -> Doc
1296 pprSizeImmOp name size imm op1
1308 pprSizeOp :: LitString -> Size -> Operand -> Doc
1309 pprSizeOp name size op1
1318 pprSizeOpOp :: LitString -> Size -> Operand -> Operand -> Doc
1319 pprSizeOpOp name size op1 op2
1325 pprOperand size op1,
1330 pprSizeByteOpOp :: LitString -> Size -> Operand -> Operand -> Doc
1331 pprSizeByteOpOp name size op1 op2
1342 pprSizeOpReg :: LitString -> Size -> Operand -> Reg -> Doc
1343 pprSizeOpReg name size op1 reg
1349 pprOperand size op1,
1354 pprSizeReg :: LitString -> Size -> Reg -> Doc
1355 pprSizeReg name size reg1
1364 pprSizeRegReg :: LitString -> Size -> Reg -> Reg -> Doc
1365 pprSizeRegReg name size reg1 reg2
1376 pprCondRegReg :: LitString -> Size -> Cond -> Reg -> Reg -> Doc
1377 pprCondRegReg name size cond reg1 reg2
1388 pprSizeSizeRegReg :: LitString -> Size -> Size -> Reg -> Reg -> Doc
1389 pprSizeSizeRegReg name size1 size2 reg1 reg2
1402 pprSizeRegRegReg :: LitString -> Size -> Reg -> Reg -> Reg -> Doc
1403 pprSizeRegRegReg name size reg1 reg2 reg3
1416 pprSizeAddr :: LitString -> Size -> MachRegsAddr -> Doc
1417 pprSizeAddr name size op
1426 pprSizeAddrReg :: LitString -> Size -> MachRegsAddr -> Reg -> Doc
1427 pprSizeAddrReg name size op dst
1438 pprSizeRegAddr :: LitString -> Size -> Reg -> MachRegsAddr -> Doc
1439 pprSizeRegAddr name size src op
1450 pprOpOp :: LitString -> Size -> Operand -> Operand -> Doc
1451 pprOpOp name size op1 op2
1455 pprOperand size op1,
1460 pprSizeOpOpCoerce :: LitString -> Size -> Size -> Operand -> Operand -> Doc
1461 pprSizeOpOpCoerce name size1 size2 op1 op2
1462 = hcat [ char '\t', ptext name, pprSize size1, pprSize size2, space,
1463 pprOperand size1 op1,
1465 pprOperand size2 op2
1468 pprCondInstr :: LitString -> Cond -> Doc -> Doc
1469 pprCondInstr name cond arg
1470 = hcat [ char '\t', ptext name, pprCond cond, space, arg]
1472 #endif {-i386_TARGET_ARCH-}
1475 %************************************************************************
1477 \subsubsection{@pprInstr@ for a SPARC}
1479 %************************************************************************
1482 #if sparc_TARGET_ARCH
1484 -- a clumsy hack for now, to handle possible double alignment problems
1486 -- even clumsier, to allow for RegReg regs that show when doing indexed
1487 -- reads (bytearrays).
1490 -- Translate to the following:
1493 -- ld [g1+4],%f(n+1)
1494 -- sub g1,g2,g1 -- to restore g1
1495 pprInstr (LD DF (AddrRegReg g1 g2) reg)
1497 hcat [ptext SLIT("\tadd\t"), pprReg g1,comma,pprReg g2,comma,pprReg g1],
1498 hcat [pp_ld_lbracket, pprReg g1, pp_rbracket_comma, pprReg reg],
1499 hcat [pp_ld_lbracket, pprReg g1, ptext SLIT("+4]"), comma, pprReg (fPair reg)],
1500 hcat [ptext SLIT("\tsub\t"), pprReg g1,comma,pprReg g2,comma,pprReg g1]
1505 -- ld [addr+4],%f(n+1)
1506 pprInstr (LD DF addr reg) | isJust off_addr
1508 hcat [pp_ld_lbracket, pprAddr addr, pp_rbracket_comma, pprReg reg],
1509 hcat [pp_ld_lbracket, pprAddr addr2, pp_rbracket_comma,pprReg (fPair reg)]
1512 off_addr = addrOffset addr 4
1513 addr2 = case off_addr of Just x -> x
1516 pprInstr (LD size addr reg)
1527 -- The same clumsy hack as above
1529 -- Translate to the following:
1532 -- st %f(n+1),[g1+4]
1533 -- sub g1,g2,g1 -- to restore g1
1534 pprInstr (ST DF reg (AddrRegReg g1 g2))
1536 hcat [ptext SLIT("\tadd\t"), pprReg g1,comma,pprReg g2,comma,pprReg g1],
1537 hcat [ptext SLIT("\tst\t"), pprReg reg, pp_comma_lbracket,
1539 hcat [ptext SLIT("\tst\t"), pprReg (fPair reg), pp_comma_lbracket,
1540 pprReg g1, ptext SLIT("+4]")],
1541 hcat [ptext SLIT("\tsub\t"), pprReg g1,comma,pprReg g2,comma,pprReg g1]
1546 -- st %f(n+1),[addr+4]
1547 pprInstr (ST DF reg addr) | isJust off_addr
1549 hcat [ptext SLIT("\tst\t"), pprReg reg, pp_comma_lbracket,
1550 pprAddr addr, rbrack],
1551 hcat [ptext SLIT("\tst\t"), pprReg (fPair reg), pp_comma_lbracket,
1552 pprAddr addr2, rbrack]
1555 off_addr = addrOffset addr 4
1556 addr2 = case off_addr of Just x -> x
1558 -- no distinction is made between signed and unsigned bytes on stores for the
1559 -- Sparc opcodes (at least I cannot see any, and gas is nagging me --SOF),
1560 -- so we call a special-purpose pprSize for ST..
1562 pprInstr (ST size reg addr)
1573 pprInstr (ADD x cc reg1 ri reg2)
1574 | not x && not cc && riZero ri
1575 = hcat [ ptext SLIT("\tmov\t"), pprReg reg1, comma, pprReg reg2 ]
1577 = pprRegRIReg (if x then SLIT("addx") else SLIT("add")) cc reg1 ri reg2
1579 pprInstr (SUB x cc reg1 ri reg2)
1580 | not x && cc && reg2 == g0
1581 = hcat [ ptext SLIT("\tcmp\t"), pprReg reg1, comma, pprRI ri ]
1582 | not x && not cc && riZero ri
1583 = hcat [ ptext SLIT("\tmov\t"), pprReg reg1, comma, pprReg reg2 ]
1585 = pprRegRIReg (if x then SLIT("subx") else SLIT("sub")) cc reg1 ri reg2
1587 pprInstr (AND b reg1 ri reg2) = pprRegRIReg SLIT("and") b reg1 ri reg2
1588 pprInstr (ANDN b reg1 ri reg2) = pprRegRIReg SLIT("andn") b reg1 ri reg2
1590 pprInstr (OR b reg1 ri reg2)
1591 | not b && reg1 == g0
1592 = let doit = hcat [ ptext SLIT("\tmov\t"), pprRI ri, comma, pprReg reg2 ]
1594 RIReg rrr | rrr == reg2 -> empty
1597 = pprRegRIReg SLIT("or") b reg1 ri reg2
1599 pprInstr (ORN b reg1 ri reg2) = pprRegRIReg SLIT("orn") b reg1 ri reg2
1601 pprInstr (XOR b reg1 ri reg2) = pprRegRIReg SLIT("xor") b reg1 ri reg2
1602 pprInstr (XNOR b reg1 ri reg2) = pprRegRIReg SLIT("xnor") b reg1 ri reg2
1604 pprInstr (SLL reg1 ri reg2) = pprRegRIReg SLIT("sll") False reg1 ri reg2
1605 pprInstr (SRL reg1 ri reg2) = pprRegRIReg SLIT("srl") False reg1 ri reg2
1606 pprInstr (SRA reg1 ri reg2) = pprRegRIReg SLIT("sra") False reg1 ri reg2
1608 pprInstr (RDY rd) = ptext SLIT("\trd\t%y,") <> pprReg rd
1609 pprInstr (SMUL b reg1 ri reg2) = pprRegRIReg SLIT("smul") b reg1 ri reg2
1610 pprInstr (UMUL b reg1 ri reg2) = pprRegRIReg SLIT("umul") b reg1 ri reg2
1612 pprInstr (SETHI imm reg)
1614 ptext SLIT("\tsethi\t"),
1620 pprInstr NOP = ptext SLIT("\tnop")
1622 pprInstr (FABS F reg1 reg2) = pprSizeRegReg SLIT("fabs") F reg1 reg2
1623 pprInstr (FABS DF reg1 reg2)
1624 = (<>) (pprSizeRegReg SLIT("fabs") F reg1 reg2)
1625 (if (reg1 == reg2) then empty
1626 else (<>) (char '\n')
1627 (pprSizeRegReg SLIT("fmov") F (fPair reg1) (fPair reg2)))
1629 pprInstr (FADD size reg1 reg2 reg3)
1630 = pprSizeRegRegReg SLIT("fadd") size reg1 reg2 reg3
1631 pprInstr (FCMP e size reg1 reg2)
1632 = pprSizeRegReg (if e then SLIT("fcmpe") else SLIT("fcmp")) size reg1 reg2
1633 pprInstr (FDIV size reg1 reg2 reg3)
1634 = pprSizeRegRegReg SLIT("fdiv") size reg1 reg2 reg3
1636 pprInstr (FMOV F reg1 reg2) = pprSizeRegReg SLIT("fmov") F reg1 reg2
1637 pprInstr (FMOV DF reg1 reg2)
1638 = (<>) (pprSizeRegReg SLIT("fmov") F reg1 reg2)
1639 (if (reg1 == reg2) then empty
1640 else (<>) (char '\n')
1641 (pprSizeRegReg SLIT("fmov") F (fPair reg1) (fPair reg2)))
1643 pprInstr (FMUL size reg1 reg2 reg3)
1644 = pprSizeRegRegReg SLIT("fmul") size reg1 reg2 reg3
1646 pprInstr (FNEG F reg1 reg2) = pprSizeRegReg SLIT("fneg") F reg1 reg2
1647 pprInstr (FNEG DF reg1 reg2)
1648 = (<>) (pprSizeRegReg SLIT("fneg") F reg1 reg2)
1649 (if (reg1 == reg2) then empty
1650 else (<>) (char '\n')
1651 (pprSizeRegReg SLIT("fmov") F (fPair reg1) (fPair reg2)))
1653 pprInstr (FSQRT size reg1 reg2) = pprSizeRegReg SLIT("fsqrt") size reg1 reg2
1654 pprInstr (FSUB size reg1 reg2 reg3) = pprSizeRegRegReg SLIT("fsub") size reg1 reg2 reg3
1655 pprInstr (FxTOy size1 size2 reg1 reg2)
1668 pprReg reg1, comma, pprReg reg2
1672 pprInstr (BI cond b lab)
1674 ptext SLIT("\tb"), pprCond cond,
1675 if b then pp_comma_a else empty,
1680 pprInstr (BF cond b lab)
1682 ptext SLIT("\tfb"), pprCond cond,
1683 if b then pp_comma_a else empty,
1688 pprInstr (JMP dsts addr) = (<>) (ptext SLIT("\tjmp\t")) (pprAddr addr)
1690 pprInstr (CALL (Left imm) n _)
1691 = hcat [ ptext SLIT("\tcall\t"), pprImm imm, comma, int n ]
1692 pprInstr (CALL (Right reg) n _)
1693 = hcat [ ptext SLIT("\tcall\t"), pprReg reg, comma, int n ]
1696 Continue with SPARC-only printing bits and bobs:
1699 pprRI (RIReg r) = pprReg r
1700 pprRI (RIImm r) = pprImm r
1702 pprSizeRegReg :: LitString -> Size -> Reg -> Reg -> Doc
1703 pprSizeRegReg name size reg1 reg2
1708 F -> ptext SLIT("s\t")
1709 DF -> ptext SLIT("d\t")),
1715 pprSizeRegRegReg :: LitString -> Size -> Reg -> Reg -> Reg -> Doc
1716 pprSizeRegRegReg name size reg1 reg2 reg3
1721 F -> ptext SLIT("s\t")
1722 DF -> ptext SLIT("d\t")),
1730 pprRegRIReg :: LitString -> Bool -> Reg -> RI -> Reg -> Doc
1731 pprRegRIReg name b reg1 ri reg2
1735 if b then ptext SLIT("cc\t") else char '\t',
1743 pprRIReg :: LitString -> Bool -> RI -> Reg -> Doc
1744 pprRIReg name b ri reg1
1748 if b then ptext SLIT("cc\t") else char '\t',
1754 pp_ld_lbracket = ptext SLIT("\tld\t[")
1755 pp_rbracket_comma = text "],"
1756 pp_comma_lbracket = text ",["
1757 pp_comma_a = text ",a"
1759 #endif {-sparc_TARGET_ARCH-}