1 -----------------------------------------------------------------------------
3 -- Pretty-printing assembly language
5 -- (c) The University of Glasgow 1993-2005
7 -----------------------------------------------------------------------------
20 #include "nativeGen/NCG.h"
21 #include "HsVersions.h"
31 import CLabel ( mkAsmTempLabel )
33 import Unique ( pprUnique )
36 import qualified Outputable
37 import Outputable ( panic )
39 import Data.Word(Word32)
43 pprUserReg :: Reg -> Doc
50 RealReg i -> ppr_reg_no i
51 VirtualRegI u -> text "%vI_" <> asmSDoc (pprUnique u)
52 VirtualRegHi u -> text "%vHi_" <> asmSDoc (pprUnique u)
53 VirtualRegF u -> text "%vF_" <> asmSDoc (pprUnique u)
54 VirtualRegD u -> text "%vD_" <> asmSDoc (pprUnique u)
57 ppr_reg_no :: Int -> Doc
60 0 -> sLit "r0"; 1 -> sLit "r1";
61 2 -> sLit "r2"; 3 -> sLit "r3";
62 4 -> sLit "r4"; 5 -> sLit "r5";
63 6 -> sLit "r6"; 7 -> sLit "r7";
64 8 -> sLit "r8"; 9 -> sLit "r9";
65 10 -> sLit "r10"; 11 -> sLit "r11";
66 12 -> sLit "r12"; 13 -> sLit "r13";
67 14 -> sLit "r14"; 15 -> sLit "r15";
68 16 -> sLit "r16"; 17 -> sLit "r17";
69 18 -> sLit "r18"; 19 -> sLit "r19";
70 20 -> sLit "r20"; 21 -> sLit "r21";
71 22 -> sLit "r22"; 23 -> sLit "r23";
72 24 -> sLit "r24"; 25 -> sLit "r25";
73 26 -> sLit "r26"; 27 -> sLit "r27";
74 28 -> sLit "r28"; 29 -> sLit "r29";
75 30 -> sLit "r30"; 31 -> sLit "r31";
76 32 -> sLit "f0"; 33 -> sLit "f1";
77 34 -> sLit "f2"; 35 -> sLit "f3";
78 36 -> sLit "f4"; 37 -> sLit "f5";
79 38 -> sLit "f6"; 39 -> sLit "f7";
80 40 -> sLit "f8"; 41 -> sLit "f9";
81 42 -> sLit "f10"; 43 -> sLit "f11";
82 44 -> sLit "f12"; 45 -> sLit "f13";
83 46 -> sLit "f14"; 47 -> sLit "f15";
84 48 -> sLit "f16"; 49 -> sLit "f17";
85 50 -> sLit "f18"; 51 -> sLit "f19";
86 52 -> sLit "f20"; 53 -> sLit "f21";
87 54 -> sLit "f22"; 55 -> sLit "f23";
88 56 -> sLit "f24"; 57 -> sLit "f25";
89 58 -> sLit "f26"; 59 -> sLit "f27";
90 60 -> sLit "f28"; 61 -> sLit "f29";
91 62 -> sLit "f30"; 63 -> sLit "f31";
92 _ -> sLit "very naughty powerpc register"
95 ppr_reg_no :: Int -> Doc
96 ppr_reg_no i | i <= 31 = int i -- GPRs
97 | i <= 63 = int (i-32) -- FPRs
98 | otherwise = ptext (sLit "very naughty powerpc register")
103 pprSize :: Size -> Doc
111 _ -> panic "PPC.Ppr.pprSize: no match")
114 pprCond :: Cond -> Doc
118 EQQ -> sLit "eq"; NE -> sLit "ne";
119 LTT -> sLit "lt"; GE -> sLit "ge";
120 GTT -> sLit "gt"; LE -> sLit "le";
121 LU -> sLit "lt"; GEU -> sLit "ge";
122 GU -> sLit "gt"; LEU -> sLit "le"; })
127 pprImm (ImmInt i) = int i
128 pprImm (ImmInteger i) = integer i
129 pprImm (ImmCLbl l) = pprCLabel_asm l
130 pprImm (ImmIndex l i) = pprCLabel_asm l <> char '+' <> int i
131 pprImm (ImmLit s) = s
133 pprImm (ImmFloat _) = ptext (sLit "naughty float immediate")
134 pprImm (ImmDouble _) = ptext (sLit "naughty double immediate")
136 pprImm (ImmConstantSum a b) = pprImm a <> char '+' <> pprImm b
137 pprImm (ImmConstantDiff a b) = pprImm a <> char '-'
138 <> lparen <> pprImm b <> rparen
142 = hcat [ pp_lo, pprImm i, rparen ]
147 = hcat [ pp_hi, pprImm i, rparen ]
152 = hcat [ pp_ha, pprImm i, rparen ]
158 = pprImm i <> text "@l"
161 = pprImm i <> text "@h"
164 = pprImm i <> text "@ha"
169 pprAddr :: AddrMode -> Doc
170 pprAddr (AddrRegReg r1 r2)
171 = pprReg r1 <+> ptext (sLit ", ") <+> pprReg r2
173 pprAddr (AddrRegImm r1 (ImmInt i)) = hcat [ int i, char '(', pprReg r1, char ')' ]
174 pprAddr (AddrRegImm r1 (ImmInteger i)) = hcat [ integer i, char '(', pprReg r1, char ')' ]
175 pprAddr (AddrRegImm r1 imm) = hcat [ pprImm imm, char '(', pprReg r1, char ')' ]
178 pprSectionHeader :: Section -> Doc
182 Text -> ptext (sLit ".text\n.align 2")
183 Data -> ptext (sLit ".data\n.align 2")
184 ReadOnlyData -> ptext (sLit ".const\n.align 2")
185 RelocatableReadOnlyData -> ptext (sLit ".const_data\n.align 2")
186 UninitialisedData -> ptext (sLit ".const_data\n.align 2")
187 ReadOnlyData16 -> ptext (sLit ".const\n.align 4")
188 OtherSection _ -> panic "PprMach.pprSectionHeader: unknown section"
193 Text -> ptext (sLit ".text\n.align 2")
194 Data -> ptext (sLit ".data\n.align 2")
195 ReadOnlyData -> ptext (sLit ".section .rodata\n\t.align 2")
196 RelocatableReadOnlyData -> ptext (sLit ".data\n\t.align 2")
197 UninitialisedData -> ptext (sLit ".section .bss\n\t.align 2")
198 ReadOnlyData16 -> ptext (sLit ".section .rodata\n\t.align 4")
199 OtherSection _ -> panic "PprMach.pprSectionHeader: unknown section"
204 pprDataItem :: CmmLit -> Doc
206 = vcat (ppr_item (cmmTypeSize $ cmmLitType lit) lit)
210 ppr_item II8 _ = [ptext (sLit "\t.byte\t") <> pprImm imm]
212 ppr_item II32 _ = [ptext (sLit "\t.long\t") <> pprImm imm]
214 ppr_item FF32 (CmmFloat r _)
215 = let bs = floatToBytes (fromRational r)
216 in map (\b -> ptext (sLit "\t.byte\t") <> pprImm (ImmInt b)) bs
218 ppr_item FF64 (CmmFloat r _)
219 = let bs = doubleToBytes (fromRational r)
220 in map (\b -> ptext (sLit "\t.byte\t") <> pprImm (ImmInt b)) bs
222 ppr_item II16 _ = [ptext (sLit "\t.short\t") <> pprImm imm]
224 ppr_item II64 (CmmInt x _) =
225 [ptext (sLit "\t.long\t")
227 (fromIntegral (x `shiftR` 32) :: Word32)),
228 ptext (sLit "\t.long\t")
229 <> int (fromIntegral (fromIntegral x :: Word32))]
232 = panic "PPC.Ppr.pprDataItem: no match"
235 pprInstr :: Instr -> Doc
237 pprInstr (COMMENT _) = empty -- nuke 'em
240 = IF_ARCH_alpha( ((<>) (ptext (sLit "\t# ")) (ftext s))
241 ,IF_ARCH_sparc( ((<>) (ptext (sLit "# ")) (ftext s))
242 ,IF_ARCH_i386( ((<>) (ptext (sLit "# ")) (ftext s))
243 ,IF_ARCH_x86_64( ((<>) (ptext (sLit "# ")) (ftext s))
244 ,IF_ARCH_powerpc( IF_OS_linux(
245 ((<>) (ptext (sLit "# ")) (ftext s)),
246 ((<>) (ptext (sLit "; ")) (ftext s)))
250 = pprInstr (COMMENT (mkFastString ("\tdelta = " ++ show d)))
252 pprInstr (NEWBLOCK _)
253 = panic "PprMach.pprInstr: NEWBLOCK"
256 = panic "PprMach.pprInstr: LDATA"
259 pprInstr (SPILL reg slot)
261 ptext (sLit "\tSPILL"),
265 ptext (sLit "SLOT") <> parens (int slot)]
267 pprInstr (RELOAD slot reg)
269 ptext (sLit "\tRELOAD"),
271 ptext (sLit "SLOT") <> parens (int slot),
275 pprInstr (LD sz reg addr) = hcat [
284 _ -> panic "PPC.Ppr.pprInstr: no match"
286 case addr of AddrRegImm _ _ -> empty
287 AddrRegReg _ _ -> char 'x',
293 pprInstr (LA sz reg addr) = hcat [
302 _ -> panic "PPC.Ppr.pprInstr: no match"
304 case addr of AddrRegImm _ _ -> empty
305 AddrRegReg _ _ -> char 'x',
311 pprInstr (ST sz reg addr) = hcat [
315 case addr of AddrRegImm _ _ -> empty
316 AddrRegReg _ _ -> char 'x',
322 pprInstr (STU sz reg addr) = hcat [
327 case addr of AddrRegImm _ _ -> empty
328 AddrRegReg _ _ -> char 'x',
333 pprInstr (LIS reg imm) = hcat [
341 pprInstr (LI reg imm) = hcat [
349 pprInstr (MR reg1 reg2)
350 | reg1 == reg2 = empty
353 case regClass reg1 of
354 RcInteger -> ptext (sLit "mr")
355 _ -> ptext (sLit "fmr"),
361 pprInstr (CMP sz reg ri) = hcat [
377 pprInstr (CMPL sz reg ri) = hcat [
393 pprInstr (BCC cond (BlockId id)) = hcat [
400 where lbl = mkAsmTempLabel id
402 pprInstr (BCCFAR cond (BlockId id)) = vcat [
405 pprCond (condNegate cond),
409 ptext (sLit "\tb\t"),
413 where lbl = mkAsmTempLabel id
415 pprInstr (JMP lbl) = hcat [ -- an alias for b that takes a CLabel
422 pprInstr (MTCTR reg) = hcat [
424 ptext (sLit "mtctr"),
428 pprInstr (BCTR _) = hcat [
432 pprInstr (BL lbl _) = hcat [
433 ptext (sLit "\tbl\t"),
436 pprInstr (BCTRL _) = hcat [
440 pprInstr (ADD reg1 reg2 ri) = pprLogic (sLit "add") reg1 reg2 ri
441 pprInstr (ADDIS reg1 reg2 imm) = hcat [
443 ptext (sLit "addis"),
452 pprInstr (ADDC reg1 reg2 reg3) = pprLogic (sLit "addc") reg1 reg2 (RIReg reg3)
453 pprInstr (ADDE reg1 reg2 reg3) = pprLogic (sLit "adde") reg1 reg2 (RIReg reg3)
454 pprInstr (SUBF reg1 reg2 reg3) = pprLogic (sLit "subf") reg1 reg2 (RIReg reg3)
455 pprInstr (MULLW reg1 reg2 ri@(RIReg _)) = pprLogic (sLit "mullw") reg1 reg2 ri
456 pprInstr (MULLW reg1 reg2 ri@(RIImm _)) = pprLogic (sLit "mull") reg1 reg2 ri
457 pprInstr (DIVW reg1 reg2 reg3) = pprLogic (sLit "divw") reg1 reg2 (RIReg reg3)
458 pprInstr (DIVWU reg1 reg2 reg3) = pprLogic (sLit "divwu") reg1 reg2 (RIReg reg3)
460 pprInstr (MULLW_MayOflo reg1 reg2 reg3) = vcat [
461 hcat [ ptext (sLit "\tmullwo\t"), pprReg reg1, ptext (sLit ", "),
462 pprReg reg2, ptext (sLit ", "),
464 hcat [ ptext (sLit "\tmfxer\t"), pprReg reg1 ],
465 hcat [ ptext (sLit "\trlwinm\t"), pprReg reg1, ptext (sLit ", "),
466 pprReg reg1, ptext (sLit ", "),
467 ptext (sLit "2, 31, 31") ]
470 -- for some reason, "andi" doesn't exist.
471 -- we'll use "andi." instead.
472 pprInstr (AND reg1 reg2 (RIImm imm)) = hcat [
474 ptext (sLit "andi."),
482 pprInstr (AND reg1 reg2 ri) = pprLogic (sLit "and") reg1 reg2 ri
484 pprInstr (OR reg1 reg2 ri) = pprLogic (sLit "or") reg1 reg2 ri
485 pprInstr (XOR reg1 reg2 ri) = pprLogic (sLit "xor") reg1 reg2 ri
487 pprInstr (XORIS reg1 reg2 imm) = hcat [
489 ptext (sLit "xoris"),
498 pprInstr (EXTS sz reg1 reg2) = hcat [
508 pprInstr (NEG reg1 reg2) = pprUnary (sLit "neg") reg1 reg2
509 pprInstr (NOT reg1 reg2) = pprUnary (sLit "not") reg1 reg2
511 pprInstr (SLW reg1 reg2 ri) = pprLogic (sLit "slw") reg1 reg2 (limitShiftRI ri)
512 pprInstr (SRW reg1 reg2 ri) = pprLogic (sLit "srw") reg1 reg2 (limitShiftRI ri)
513 pprInstr (SRAW reg1 reg2 ri) = pprLogic (sLit "sraw") reg1 reg2 (limitShiftRI ri)
514 pprInstr (RLWINM reg1 reg2 sh mb me) = hcat [
515 ptext (sLit "\trlwinm\t"),
527 pprInstr (FADD sz reg1 reg2 reg3) = pprBinaryF (sLit "fadd") sz reg1 reg2 reg3
528 pprInstr (FSUB sz reg1 reg2 reg3) = pprBinaryF (sLit "fsub") sz reg1 reg2 reg3
529 pprInstr (FMUL sz reg1 reg2 reg3) = pprBinaryF (sLit "fmul") sz reg1 reg2 reg3
530 pprInstr (FDIV sz reg1 reg2 reg3) = pprBinaryF (sLit "fdiv") sz reg1 reg2 reg3
531 pprInstr (FNEG reg1 reg2) = pprUnary (sLit "fneg") reg1 reg2
533 pprInstr (FCMP reg1 reg2) = hcat [
535 ptext (sLit "fcmpu\tcr0, "),
536 -- Note: we're using fcmpu, not fcmpo
537 -- The difference is with fcmpo, compare with NaN is an invalid operation.
538 -- We don't handle invalid fp ops, so we don't care
544 pprInstr (FCTIWZ reg1 reg2) = pprUnary (sLit "fctiwz") reg1 reg2
545 pprInstr (FRSP reg1 reg2) = pprUnary (sLit "frsp") reg1 reg2
547 pprInstr (CRNOR dst src1 src2) = hcat [
548 ptext (sLit "\tcrnor\t"),
556 pprInstr (MFCR reg) = hcat [
563 pprInstr (MFLR reg) = hcat [
570 pprInstr (FETCHPC reg) = vcat [
571 ptext (sLit "\tbcl\t20,31,1f"),
572 hcat [ ptext (sLit "1:\tmflr\t"), pprReg reg ]
575 pprInstr LWSYNC = ptext (sLit "\tlwsync")
577 -- pprInstr _ = panic "pprInstr (ppc)"
580 pprLogic :: LitString -> Reg -> Reg -> RI -> Doc
581 pprLogic op reg1 reg2 ri = hcat [
596 pprUnary :: LitString -> Reg -> Reg -> Doc
597 pprUnary op reg1 reg2 = hcat [
607 pprBinaryF :: LitString -> Size -> Reg -> Reg -> Reg -> Doc
608 pprBinaryF op sz reg1 reg2 reg3 = hcat [
621 pprRI (RIReg r) = pprReg r
622 pprRI (RIImm r) = pprImm r
625 pprFSize :: Size -> Doc
626 pprFSize FF64 = empty
627 pprFSize FF32 = char 's'
628 pprFSize _ = panic "PPC.Ppr.pprFSize: no match"
630 -- limit immediate argument for shift instruction to range 0..32
631 -- (yes, the maximum is really 32, not 31)
632 limitShiftRI :: RI -> RI
633 limitShiftRI (RIImm (ImmInt i)) | i > 32 || i < 0 = RIImm (ImmInt 32)