1 -----------------------------------------------------------------------------
3 -- Pretty-printing assembly language
5 -- (c) The University of Glasgow 1993-2005
7 -----------------------------------------------------------------------------
23 #include "HsVersions.h"
24 #include "nativeGen/NCG.h"
38 import Unique ( pprUnique )
41 import qualified Outputable
42 import Outputable (panic, Outputable)
48 -- -----------------------------------------------------------------------------
49 -- Printing this stuff out
51 pprNatCmmTop :: NatCmmTop Instr -> Doc
52 pprNatCmmTop (CmmData section dats) =
53 pprSectionHeader section $$ vcat (map pprData dats)
55 -- special case for split markers:
56 pprNatCmmTop (CmmProc [] lbl _ (ListGraph [])) = pprLabel lbl
58 pprNatCmmTop (CmmProc info lbl _ (ListGraph blocks)) =
59 pprSectionHeader Text $$
60 (if null info then -- blocks guaranteed not null, so label needed
63 #if HAVE_SUBSECTIONS_VIA_SYMBOLS
64 pprCLabel_asm (mkDeadStripPreventer $ entryLblToInfoLbl lbl)
67 vcat (map pprData info) $$
68 pprLabel (entryLblToInfoLbl lbl)
70 vcat (map pprBasicBlock blocks)
71 -- above: Even the first block gets a label, because with branch-chain
72 -- elimination, it might be the target of a goto.
73 #if HAVE_SUBSECTIONS_VIA_SYMBOLS
74 -- If we are using the .subsections_via_symbols directive
75 -- (available on recent versions of Darwin),
76 -- we have to make sure that there is some kind of reference
77 -- from the entry code to a label on the _top_ of of the info table,
78 -- so that the linker will not think it is unreferenced and dead-strip
79 -- it. That's why the label is called a DeadStripPreventer (_dsp).
82 <+> pprCLabel_asm (entryLblToInfoLbl lbl)
84 <+> pprCLabel_asm (mkDeadStripPreventer $ entryLblToInfoLbl lbl)
89 pprBasicBlock :: NatBasicBlock Instr -> Doc
90 pprBasicBlock (BasicBlock (BlockId id) instrs) =
91 pprLabel (mkAsmTempLabel id) $$
92 vcat (map pprInstr instrs)
95 pprData :: CmmStatic -> Doc
96 pprData (CmmAlign bytes) = pprAlign bytes
97 pprData (CmmDataLabel lbl) = pprLabel lbl
98 pprData (CmmString str) = pprASCII str
99 pprData (CmmUninitialised bytes) = ptext (sLit ".skip ") <> int bytes
100 pprData (CmmStaticLit lit) = pprDataItem lit
102 pprGloblDecl :: CLabel -> Doc
104 | not (externallyVisibleCLabel lbl) = empty
105 | otherwise = ptext IF_ARCH_sparc((sLit ".global "),
109 pprTypeAndSizeDecl :: CLabel -> Doc
111 pprTypeAndSizeDecl lbl
112 | not (externallyVisibleCLabel lbl) = empty
113 | otherwise = ptext (sLit ".type ") <>
114 pprCLabel_asm lbl <> ptext (sLit ", @object")
120 pprLabel :: CLabel -> Doc
121 pprLabel lbl = pprGloblDecl lbl $$ pprTypeAndSizeDecl lbl $$ (pprCLabel_asm lbl <> char ':')
124 pprASCII :: [Word8] -> Doc
126 = vcat (map do1 str) $$ do1 0
129 do1 w = ptext (sLit "\t.byte\t") <> int (fromIntegral w)
131 pprAlign :: Int -> Doc
135 = ptext (sLit ".align ") <> int IF_OS_darwin(pow2, bytes)
141 log2 :: Int -> Int -- cache the common ones
146 log2 n = 1 + log2 (n `quot` 2)
149 -- -----------------------------------------------------------------------------
150 -- pprInstr: print an 'Instr'
152 instance Outputable Instr where
153 ppr instr = Outputable.docToSDoc $ pprInstr instr
166 #if i386_TARGET_ARCH || x86_64_TARGET_ARCH
167 pprUserReg :: Reg -> Doc
168 pprUserReg = pprReg IF_ARCH_i386(II32,) IF_ARCH_x86_64(II64,)
171 pprUserReg :: Reg -> Doc
172 pprUserReg = panic "X86.Ppr.pprUserReg: not defined"
176 pprReg :: Size -> Reg -> Doc
180 RealReg i -> ppr_reg_no s i
181 VirtualRegI u -> text "%vI_" <> asmSDoc (pprUnique u)
182 VirtualRegHi u -> text "%vHi_" <> asmSDoc (pprUnique u)
183 VirtualRegF u -> text "%vF_" <> asmSDoc (pprUnique u)
184 VirtualRegD u -> text "%vD_" <> asmSDoc (pprUnique u)
187 ppr_reg_no :: Size -> Int -> Doc
188 ppr_reg_no II8 = ppr_reg_byte
189 ppr_reg_no II16 = ppr_reg_word
190 ppr_reg_no _ = ppr_reg_long
192 ppr_reg_byte i = ptext
194 0 -> sLit "%al"; 1 -> sLit "%bl";
195 2 -> sLit "%cl"; 3 -> sLit "%dl";
196 _ -> sLit "very naughty I386 byte register"
199 ppr_reg_word i = ptext
201 0 -> sLit "%ax"; 1 -> sLit "%bx";
202 2 -> sLit "%cx"; 3 -> sLit "%dx";
203 4 -> sLit "%si"; 5 -> sLit "%di";
204 6 -> sLit "%bp"; 7 -> sLit "%sp";
205 _ -> sLit "very naughty I386 word register"
208 ppr_reg_long i = ptext
210 0 -> sLit "%eax"; 1 -> sLit "%ebx";
211 2 -> sLit "%ecx"; 3 -> sLit "%edx";
212 4 -> sLit "%esi"; 5 -> sLit "%edi";
213 6 -> sLit "%ebp"; 7 -> sLit "%esp";
214 8 -> sLit "%fake0"; 9 -> sLit "%fake1";
215 10 -> sLit "%fake2"; 11 -> sLit "%fake3";
216 12 -> sLit "%fake4"; 13 -> sLit "%fake5";
217 _ -> sLit "very naughty I386 register"
219 #elif x86_64_TARGET_ARCH
220 ppr_reg_no :: Size -> Int -> Doc
221 ppr_reg_no II8 = ppr_reg_byte
222 ppr_reg_no II16 = ppr_reg_word
223 ppr_reg_no II32 = ppr_reg_long
224 ppr_reg_no _ = ppr_reg_quad
226 ppr_reg_byte i = ptext
228 0 -> sLit "%al"; 1 -> sLit "%bl";
229 2 -> sLit "%cl"; 3 -> sLit "%dl";
230 4 -> sLit "%sil"; 5 -> sLit "%dil"; -- new 8-bit regs!
231 6 -> sLit "%bpl"; 7 -> sLit "%spl";
232 8 -> sLit "%r8b"; 9 -> sLit "%r9b";
233 10 -> sLit "%r10b"; 11 -> sLit "%r11b";
234 12 -> sLit "%r12b"; 13 -> sLit "%r13b";
235 14 -> sLit "%r14b"; 15 -> sLit "%r15b";
236 _ -> sLit "very naughty x86_64 byte register"
239 ppr_reg_word i = ptext
241 0 -> sLit "%ax"; 1 -> sLit "%bx";
242 2 -> sLit "%cx"; 3 -> sLit "%dx";
243 4 -> sLit "%si"; 5 -> sLit "%di";
244 6 -> sLit "%bp"; 7 -> sLit "%sp";
245 8 -> sLit "%r8w"; 9 -> sLit "%r9w";
246 10 -> sLit "%r10w"; 11 -> sLit "%r11w";
247 12 -> sLit "%r12w"; 13 -> sLit "%r13w";
248 14 -> sLit "%r14w"; 15 -> sLit "%r15w";
249 _ -> sLit "very naughty x86_64 word register"
252 ppr_reg_long i = ptext
254 0 -> sLit "%eax"; 1 -> sLit "%ebx";
255 2 -> sLit "%ecx"; 3 -> sLit "%edx";
256 4 -> sLit "%esi"; 5 -> sLit "%edi";
257 6 -> sLit "%ebp"; 7 -> sLit "%esp";
258 8 -> sLit "%r8d"; 9 -> sLit "%r9d";
259 10 -> sLit "%r10d"; 11 -> sLit "%r11d";
260 12 -> sLit "%r12d"; 13 -> sLit "%r13d";
261 14 -> sLit "%r14d"; 15 -> sLit "%r15d";
262 _ -> sLit "very naughty x86_64 register"
265 ppr_reg_quad i = ptext
267 0 -> sLit "%rax"; 1 -> sLit "%rbx";
268 2 -> sLit "%rcx"; 3 -> sLit "%rdx";
269 4 -> sLit "%rsi"; 5 -> sLit "%rdi";
270 6 -> sLit "%rbp"; 7 -> sLit "%rsp";
271 8 -> sLit "%r8"; 9 -> sLit "%r9";
272 10 -> sLit "%r10"; 11 -> sLit "%r11";
273 12 -> sLit "%r12"; 13 -> sLit "%r13";
274 14 -> sLit "%r14"; 15 -> sLit "%r15";
275 16 -> sLit "%xmm0"; 17 -> sLit "%xmm1";
276 18 -> sLit "%xmm2"; 19 -> sLit "%xmm3";
277 20 -> sLit "%xmm4"; 21 -> sLit "%xmm5";
278 22 -> sLit "%xmm6"; 23 -> sLit "%xmm7";
279 24 -> sLit "%xmm8"; 25 -> sLit "%xmm9";
280 26 -> sLit "%xmm10"; 27 -> sLit "%xmm11";
281 28 -> sLit "%xmm12"; 29 -> sLit "%xmm13";
282 30 -> sLit "%xmm14"; 31 -> sLit "%xmm15";
283 _ -> sLit "very naughty x86_64 register"
286 ppr_reg_no _ = panic "X86.Ppr.ppr_reg_no: no match"
290 pprSize :: Size -> Doc
301 #elif x86_64_TARGET_ARCH
302 FF32 -> sLit "ss" -- "scalar single-precision float" (SSE2)
303 FF64 -> sLit "sd" -- "scalar double-precision float" (SSE2)
304 _ -> panic "X86.Ppr.pprSize: no match"
306 _ -> panic "X86.Ppr.pprSize: no match"
310 pprCond :: Cond -> Doc
313 GEU -> sLit "ae"; LU -> sLit "b";
314 EQQ -> sLit "e"; GTT -> sLit "g";
315 GE -> sLit "ge"; GU -> sLit "a";
316 LTT -> sLit "l"; LE -> sLit "le";
317 LEU -> sLit "be"; NE -> sLit "ne";
318 NEG -> sLit "s"; POS -> sLit "ns";
319 CARRY -> sLit "c"; OFLO -> sLit "o";
320 PARITY -> sLit "p"; NOTPARITY -> sLit "np";
321 ALWAYS -> sLit "mp"})
325 pprImm (ImmInt i) = int i
326 pprImm (ImmInteger i) = integer i
327 pprImm (ImmCLbl l) = pprCLabel_asm l
328 pprImm (ImmIndex l i) = pprCLabel_asm l <> char '+' <> int i
329 pprImm (ImmLit s) = s
331 pprImm (ImmFloat _) = ptext (sLit "naughty float immediate")
332 pprImm (ImmDouble _) = ptext (sLit "naughty double immediate")
334 pprImm (ImmConstantSum a b) = pprImm a <> char '+' <> pprImm b
335 pprImm (ImmConstantDiff a b) = pprImm a <> char '-'
336 <> lparen <> pprImm b <> rparen
340 pprAddr :: AddrMode -> Doc
341 pprAddr (ImmAddr imm off)
342 = let pp_imm = pprImm imm
346 else if (off < 0) then
349 pp_imm <> char '+' <> int off
351 pprAddr (AddrBaseIndex base index displacement)
353 pp_disp = ppr_disp displacement
354 pp_off p = pp_disp <> char '(' <> p <> char ')'
355 pp_reg r = pprReg archWordSize r
357 case (base, index) of
358 (EABaseNone, EAIndexNone) -> pp_disp
359 (EABaseReg b, EAIndexNone) -> pp_off (pp_reg b)
360 (EABaseRip, EAIndexNone) -> pp_off (ptext (sLit "%rip"))
361 (EABaseNone, EAIndex r i) -> pp_off (comma <> pp_reg r <> comma <> int i)
362 (EABaseReg b, EAIndex r i) -> pp_off (pp_reg b <> comma <> pp_reg r
364 _ -> panic "X86.Ppr.pprAddr: no match"
367 ppr_disp (ImmInt 0) = empty
368 ppr_disp imm = pprImm imm
371 pprSectionHeader :: Section -> Doc
374 # if darwin_TARGET_OS
377 Text -> ptext (sLit ".text\n\t.align 2")
378 Data -> ptext (sLit ".data\n\t.align 2")
379 ReadOnlyData -> ptext (sLit ".const\n.align 2")
380 RelocatableReadOnlyData -> ptext (sLit ".const_data\n.align 2")
381 UninitialisedData -> ptext (sLit ".data\n\t.align 2")
382 ReadOnlyData16 -> ptext (sLit ".const\n.align 4")
383 OtherSection _ -> panic "X86.Ppr.pprSectionHeader: unknown section"
388 Text -> ptext (sLit ".text\n\t.align 4,0x90")
389 Data -> ptext (sLit ".data\n\t.align 4")
390 ReadOnlyData -> ptext (sLit ".section .rodata\n\t.align 4")
391 RelocatableReadOnlyData -> ptext (sLit ".section .data\n\t.align 4")
392 UninitialisedData -> ptext (sLit ".section .bss\n\t.align 4")
393 ReadOnlyData16 -> ptext (sLit ".section .rodata\n\t.align 16")
394 OtherSection _ -> panic "X86.Ppr.pprSectionHeader: unknown section"
398 #elif x86_64_TARGET_ARCH
399 # if darwin_TARGET_OS
402 Text -> ptext (sLit ".text\n.align 3")
403 Data -> ptext (sLit ".data\n.align 3")
404 ReadOnlyData -> ptext (sLit ".const\n.align 3")
405 RelocatableReadOnlyData -> ptext (sLit ".const_data\n.align 3")
406 UninitialisedData -> ptext (sLit ".data\n\t.align 3")
407 ReadOnlyData16 -> ptext (sLit ".const\n.align 4")
408 OtherSection _ -> panic "PprMach.pprSectionHeader: unknown section"
413 Text -> ptext (sLit ".text\n\t.align 8")
414 Data -> ptext (sLit ".data\n\t.align 8")
415 ReadOnlyData -> ptext (sLit ".section .rodata\n\t.align 8")
416 RelocatableReadOnlyData -> ptext (sLit ".section .data\n\t.align 8")
417 UninitialisedData -> ptext (sLit ".section .bss\n\t.align 8")
418 ReadOnlyData16 -> ptext (sLit ".section .rodata.cst16\n\t.align 16")
419 OtherSection _ -> panic "PprMach.pprSectionHeader: unknown section"
424 pprSectionHeader _ = panic "X86.Ppr.pprSectionHeader: not defined for this architecture"
431 pprDataItem :: CmmLit -> Doc
433 = vcat (ppr_item (cmmTypeSize $ cmmLitType lit) lit)
437 -- These seem to be common:
438 ppr_item II8 _ = [ptext (sLit "\t.byte\t") <> pprImm imm]
439 ppr_item II32 _ = [ptext (sLit "\t.long\t") <> pprImm imm]
441 ppr_item FF32 (CmmFloat r _)
442 = let bs = floatToBytes (fromRational r)
443 in map (\b -> ptext (sLit "\t.byte\t") <> pprImm (ImmInt b)) bs
445 ppr_item FF64 (CmmFloat r _)
446 = let bs = doubleToBytes (fromRational r)
447 in map (\b -> ptext (sLit "\t.byte\t") <> pprImm (ImmInt b)) bs
449 #if i386_TARGET_ARCH || x86_64_TARGET_ARCH
450 ppr_item II16 _ = [ptext (sLit "\t.word\t") <> pprImm imm]
452 #if i386_TARGET_ARCH && darwin_TARGET_OS
453 ppr_item II64 (CmmInt x _) =
454 [ptext (sLit "\t.long\t")
455 <> int (fromIntegral (fromIntegral x :: Word32)),
456 ptext (sLit "\t.long\t")
458 (fromIntegral (x `shiftR` 32) :: Word32))]
460 #if i386_TARGET_ARCH || (darwin_TARGET_OS && x86_64_TARGET_ARCH)
461 ppr_item II64 _ = [ptext (sLit "\t.quad\t") <> pprImm imm]
463 #if x86_64_TARGET_ARCH && !darwin_TARGET_OS
464 -- x86_64: binutils can't handle the R_X86_64_PC64 relocation
465 -- type, which means we can't do pc-relative 64-bit addresses.
466 -- Fortunately we're assuming the small memory model, in which
467 -- all such offsets will fit into 32 bits, so we have to stick
468 -- to 32-bit offset fields and modify the RTS appropriately
470 -- See Note [x86-64-relative] in includes/InfoTables.h
473 | isRelativeReloc x =
474 [ptext (sLit "\t.long\t") <> pprImm imm,
475 ptext (sLit "\t.long\t0")]
477 [ptext (sLit "\t.quad\t") <> pprImm imm]
479 isRelativeReloc (CmmLabelDiffOff _ _ _) = True
480 isRelativeReloc _ = False
484 = panic "X86.Ppr.ppr_item: no match"
488 pprInstr :: Instr -> Doc
490 pprInstr (COMMENT _) = empty -- nuke 'em
493 = IF_ARCH_alpha( ((<>) (ptext (sLit "\t# ")) (ftext s))
494 ,IF_ARCH_sparc( ((<>) (ptext (sLit "# ")) (ftext s))
495 ,IF_ARCH_i386( ((<>) (ptext (sLit "# ")) (ftext s))
496 ,IF_ARCH_x86_64( ((<>) (ptext (sLit "# ")) (ftext s))
497 ,IF_ARCH_powerpc( IF_OS_linux(
498 ((<>) (ptext (sLit "# ")) (ftext s)),
499 ((<>) (ptext (sLit "; ")) (ftext s)))
503 = pprInstr (COMMENT (mkFastString ("\tdelta = " ++ show d)))
505 pprInstr (NEWBLOCK _)
506 = panic "PprMach.pprInstr: NEWBLOCK"
509 = panic "PprMach.pprInstr: LDATA"
512 pprInstr (SPILL reg slot)
514 ptext (sLit "\tSPILL"),
518 ptext (sLit "SLOT") <> parens (int slot)]
520 pprInstr (RELOAD slot reg)
522 ptext (sLit "\tRELOAD"),
524 ptext (sLit "SLOT") <> parens (int slot),
529 pprInstr (MOV size src dst)
530 = pprSizeOpOp (sLit "mov") size src dst
532 pprInstr (MOVZxL II32 src dst) = pprSizeOpOp (sLit "mov") II32 src dst
533 -- 32-to-64 bit zero extension on x86_64 is accomplished by a simple
534 -- movl. But we represent it as a MOVZxL instruction, because
535 -- the reg alloc would tend to throw away a plain reg-to-reg
536 -- move, and we still want it to do that.
538 pprInstr (MOVZxL sizes src dst) = pprSizeOpOpCoerce (sLit "movz") sizes II32 src dst
539 -- zero-extension only needs to extend to 32 bits: on x86_64,
540 -- the remaining zero-extension to 64 bits is automatic, and the 32-bit
541 -- instruction is shorter.
543 pprInstr (MOVSxL sizes src dst) = pprSizeOpOpCoerce (sLit "movs") sizes archWordSize src dst
545 -- here we do some patching, since the physical registers are only set late
546 -- in the code generation.
547 pprInstr (LEA size (OpAddr (AddrBaseIndex (EABaseReg reg1) (EAIndex reg2 1) (ImmInt 0))) dst@(OpReg reg3))
549 = pprSizeOpOp (sLit "add") size (OpReg reg2) dst
551 pprInstr (LEA size (OpAddr (AddrBaseIndex (EABaseReg reg1) (EAIndex reg2 1) (ImmInt 0))) dst@(OpReg reg3))
553 = pprSizeOpOp (sLit "add") size (OpReg reg1) dst
555 pprInstr (LEA size (OpAddr (AddrBaseIndex (EABaseReg reg1) EAIndexNone displ)) dst@(OpReg reg3))
557 = pprInstr (ADD size (OpImm displ) dst)
559 pprInstr (LEA size src dst) = pprSizeOpOp (sLit "lea") size src dst
561 pprInstr (ADD size (OpImm (ImmInt (-1))) dst)
562 = pprSizeOp (sLit "dec") size dst
563 pprInstr (ADD size (OpImm (ImmInt 1)) dst)
564 = pprSizeOp (sLit "inc") size dst
565 pprInstr (ADD size src dst)
566 = pprSizeOpOp (sLit "add") size src dst
567 pprInstr (ADC size src dst)
568 = pprSizeOpOp (sLit "adc") size src dst
569 pprInstr (SUB size src dst) = pprSizeOpOp (sLit "sub") size src dst
570 pprInstr (IMUL size op1 op2) = pprSizeOpOp (sLit "imul") size op1 op2
572 {- A hack. The Intel documentation says that "The two and three
573 operand forms [of IMUL] may also be used with unsigned operands
574 because the lower half of the product is the same regardless if
575 (sic) the operands are signed or unsigned. The CF and OF flags,
576 however, cannot be used to determine if the upper half of the
577 result is non-zero." So there.
579 pprInstr (AND size src dst) = pprSizeOpOp (sLit "and") size src dst
580 pprInstr (OR size src dst) = pprSizeOpOp (sLit "or") size src dst
582 pprInstr (XOR FF32 src dst) = pprOpOp (sLit "xorps") FF32 src dst
583 pprInstr (XOR FF64 src dst) = pprOpOp (sLit "xorpd") FF64 src dst
584 pprInstr (XOR size src dst) = pprSizeOpOp (sLit "xor") size src dst
586 pprInstr (NOT size op) = pprSizeOp (sLit "not") size op
587 pprInstr (NEGI size op) = pprSizeOp (sLit "neg") size op
589 pprInstr (SHL size src dst) = pprShift (sLit "shl") size src dst
590 pprInstr (SAR size src dst) = pprShift (sLit "sar") size src dst
591 pprInstr (SHR size src dst) = pprShift (sLit "shr") size src dst
593 pprInstr (BT size imm src) = pprSizeImmOp (sLit "bt") size imm src
595 pprInstr (CMP size src dst)
596 | is_float size = pprSizeOpOp (sLit "ucomi") size src dst -- SSE2
597 | otherwise = pprSizeOpOp (sLit "cmp") size src dst
599 -- This predicate is needed here and nowhere else
605 pprInstr (TEST size src dst) = pprSizeOpOp (sLit "test") size src dst
606 pprInstr (PUSH size op) = pprSizeOp (sLit "push") size op
607 pprInstr (POP size op) = pprSizeOp (sLit "pop") size op
609 -- both unused (SDM):
610 -- pprInstr PUSHA = ptext (sLit "\tpushal")
611 -- pprInstr POPA = ptext (sLit "\tpopal")
613 pprInstr NOP = ptext (sLit "\tnop")
614 pprInstr (CLTD II32) = ptext (sLit "\tcltd")
615 pprInstr (CLTD II64) = ptext (sLit "\tcqto")
617 pprInstr (SETCC cond op) = pprCondInstr (sLit "set") cond (pprOperand II8 op)
619 pprInstr (JXX cond (BlockId id))
620 = pprCondInstr (sLit "j") cond (pprCLabel_asm lab)
621 where lab = mkAsmTempLabel id
623 pprInstr (JXX_GBL cond imm) = pprCondInstr (sLit "j") cond (pprImm imm)
625 pprInstr (JMP (OpImm imm)) = (<>) (ptext (sLit "\tjmp ")) (pprImm imm)
626 pprInstr (JMP op) = (<>) (ptext (sLit "\tjmp *")) (pprOperand archWordSize op)
627 pprInstr (JMP_TBL op _) = pprInstr (JMP op)
628 pprInstr (CALL (Left imm) _) = (<>) (ptext (sLit "\tcall ")) (pprImm imm)
629 pprInstr (CALL (Right reg) _) = (<>) (ptext (sLit "\tcall *")) (pprReg archWordSize reg)
631 pprInstr (IDIV sz op) = pprSizeOp (sLit "idiv") sz op
632 pprInstr (DIV sz op) = pprSizeOp (sLit "div") sz op
633 pprInstr (IMUL2 sz op) = pprSizeOp (sLit "imul") sz op
636 pprInstr (MUL size op1 op2) = pprSizeOpOp (sLit "mul") size op1 op2
638 pprInstr (FDIV size op1 op2) = pprSizeOpOp (sLit "div") size op1 op2
640 pprInstr (CVTSS2SD from to) = pprRegReg (sLit "cvtss2sd") from to
641 pprInstr (CVTSD2SS from to) = pprRegReg (sLit "cvtsd2ss") from to
642 pprInstr (CVTTSS2SIQ from to) = pprOpReg (sLit "cvttss2siq") from to
643 pprInstr (CVTTSD2SIQ from to) = pprOpReg (sLit "cvttsd2siq") from to
644 pprInstr (CVTSI2SS from to) = pprOpReg (sLit "cvtsi2ssq") from to
645 pprInstr (CVTSI2SD from to) = pprOpReg (sLit "cvtsi2sdq") from to
647 -- FETCHGOT for PIC on ELF platforms
648 pprInstr (FETCHGOT reg)
649 = vcat [ ptext (sLit "\tcall 1f"),
650 hcat [ ptext (sLit "1:\tpopl\t"), pprReg II32 reg ],
651 hcat [ ptext (sLit "\taddl\t$_GLOBAL_OFFSET_TABLE_+(.-1b), "),
655 -- FETCHPC for PIC on Darwin/x86
656 -- get the instruction pointer into a register
657 -- (Terminology note: the IP is called Program Counter on PPC,
658 -- and it's a good thing to use the same name on both platforms)
659 pprInstr (FETCHPC reg)
660 = vcat [ ptext (sLit "\tcall 1f"),
661 hcat [ ptext (sLit "1:\tpopl\t"), pprReg II32 reg ]
665 -- -----------------------------------------------------------------------------
666 -- i386 floating-point
668 -- Simulating a flat register set on the x86 FP stack is tricky.
669 -- you have to free %st(7) before pushing anything on the FP reg stack
670 -- so as to preclude the possibility of a FP stack overflow exception.
671 pprInstr g@(GMOV src dst)
675 = pprG g (hcat [gtab, gpush src 0, gsemi, gpop dst 1])
677 -- GLD sz addr dst ==> FFREE %st(7) ; FLDsz addr ; FSTP (dst+1)
678 pprInstr g@(GLD sz addr dst)
679 = pprG g (hcat [gtab, text "ffree %st(7) ; fld", pprSize sz, gsp,
680 pprAddr addr, gsemi, gpop dst 1])
682 -- GST sz src addr ==> FFREE %st(7) ; FLD dst ; FSTPsz addr
683 pprInstr g@(GST sz src addr)
684 = pprG g (hcat [gtab, gpush src 0, gsemi,
685 text "fstp", pprSize sz, gsp, pprAddr addr])
687 pprInstr g@(GLDZ dst)
688 = pprG g (hcat [gtab, text "ffree %st(7) ; fldz ; ", gpop dst 1])
689 pprInstr g@(GLD1 dst)
690 = pprG g (hcat [gtab, text "ffree %st(7) ; fld1 ; ", gpop dst 1])
692 pprInstr (GFTOI src dst)
693 = pprInstr (GDTOI src dst)
695 pprInstr g@(GDTOI src dst)
697 hcat [gtab, text "subl $8, %esp ; fnstcw 4(%esp)"],
698 hcat [gtab, gpush src 0],
699 hcat [gtab, text "movzwl 4(%esp), ", reg,
700 text " ; orl $0xC00, ", reg],
701 hcat [gtab, text "movl ", reg, text ", 0(%esp) ; fldcw 0(%esp)"],
702 hcat [gtab, text "fistpl 0(%esp)"],
703 hcat [gtab, text "fldcw 4(%esp) ; movl 0(%esp), ", reg],
704 hcat [gtab, text "addl $8, %esp"]
707 reg = pprReg II32 dst
709 pprInstr (GITOF src dst)
710 = pprInstr (GITOD src dst)
712 pprInstr g@(GITOD src dst)
713 = pprG g (hcat [gtab, text "pushl ", pprReg II32 src,
714 text " ; ffree %st(7); fildl (%esp) ; ",
715 gpop dst 1, text " ; addl $4,%esp"])
717 {- Gruesome swamp follows. If you're unfortunate enough to have ventured
718 this far into the jungle AND you give a Rat's Ass (tm) what's going
719 on, here's the deal. Generate code to do a floating point comparison
720 of src1 and src2, of kind cond, and set the Zero flag if true.
722 The complications are to do with handling NaNs correctly. We want the
723 property that if either argument is NaN, then the result of the
724 comparison is False ... except if we're comparing for inequality,
725 in which case the answer is True.
727 Here's how the general (non-inequality) case works. As an
728 example, consider generating the an equality test:
730 pushl %eax -- we need to mess with this
731 <get src1 to top of FPU stack>
732 fcomp <src2 location in FPU stack> and pop pushed src1
733 -- Result of comparison is in FPU Status Register bits
735 fstsw %ax -- Move FPU Status Reg to %ax
736 sahf -- move C3 C2 C0 from %ax to integer flag reg
737 -- now the serious magic begins
738 setpo %ah -- %ah = if comparable(neither arg was NaN) then 1 else 0
739 sete %al -- %al = if arg1 == arg2 then 1 else 0
740 andb %ah,%al -- %al &= %ah
741 -- so %al == 1 iff (comparable && same); else it holds 0
742 decb %al -- %al == 0, ZeroFlag=1 iff (comparable && same);
743 else %al == 0xFF, ZeroFlag=0
744 -- the zero flag is now set as we desire.
747 The special case of inequality differs thusly:
749 setpe %ah -- %ah = if incomparable(either arg was NaN) then 1 else 0
750 setne %al -- %al = if arg1 /= arg2 then 1 else 0
751 orb %ah,%al -- %al = if (incomparable || different) then 1 else 0
752 decb %al -- if (incomparable || different) then (%al == 0, ZF=1)
753 else (%al == 0xFF, ZF=0)
755 pprInstr g@(GCMP cond src1 src2)
756 | case cond of { NE -> True; _ -> False }
758 hcat [gtab, text "pushl %eax ; ",gpush src1 0],
759 hcat [gtab, text "fcomp ", greg src2 1,
760 text "; fstsw %ax ; sahf ; setpe %ah"],
761 hcat [gtab, text "setne %al ; ",
762 text "orb %ah,%al ; decb %al ; popl %eax"]
766 hcat [gtab, text "pushl %eax ; ",gpush src1 0],
767 hcat [gtab, text "fcomp ", greg src2 1,
768 text "; fstsw %ax ; sahf ; setpo %ah"],
769 hcat [gtab, text "set", pprCond (fix_FP_cond cond), text " %al ; ",
770 text "andb %ah,%al ; decb %al ; popl %eax"]
773 {- On the 486, the flags set by FP compare are the unsigned ones!
774 (This looks like a HACK to me. WDP 96/03)
776 fix_FP_cond :: Cond -> Cond
781 fix_FP_cond EQQ = EQQ
783 fix_FP_cond _ = panic "X86.Ppr.fix_FP_cond: no match"
784 -- there should be no others
787 pprInstr g@(GABS _ src dst)
788 = pprG g (hcat [gtab, gpush src 0, text " ; fabs ; ", gpop dst 1])
790 pprInstr g@(GNEG _ src dst)
791 = pprG g (hcat [gtab, gpush src 0, text " ; fchs ; ", gpop dst 1])
793 pprInstr g@(GSQRT sz src dst)
794 = pprG g (hcat [gtab, gpush src 0, text " ; fsqrt"] $$
795 hcat [gtab, gcoerceto sz, gpop dst 1])
797 pprInstr g@(GSIN sz l1 l2 src dst)
798 = pprG g (pprTrigOp "fsin" False l1 l2 src dst sz)
800 pprInstr g@(GCOS sz l1 l2 src dst)
801 = pprG g (pprTrigOp "fcos" False l1 l2 src dst sz)
803 pprInstr g@(GTAN sz l1 l2 src dst)
804 = pprG g (pprTrigOp "fptan" True l1 l2 src dst sz)
806 -- In the translations for GADD, GMUL, GSUB and GDIV,
807 -- the first two cases are mere optimisations. The otherwise clause
808 -- generates correct code under all circumstances.
810 pprInstr g@(GADD _ src1 src2 dst)
812 = pprG g (text "\t#GADD-xxxcase1" $$
813 hcat [gtab, gpush src2 0,
814 text " ; faddp %st(0),", greg src1 1])
816 = pprG g (text "\t#GADD-xxxcase2" $$
817 hcat [gtab, gpush src1 0,
818 text " ; faddp %st(0),", greg src2 1])
820 = pprG g (hcat [gtab, gpush src1 0,
821 text " ; fadd ", greg src2 1, text ",%st(0)",
825 pprInstr g@(GMUL _ src1 src2 dst)
827 = pprG g (text "\t#GMUL-xxxcase1" $$
828 hcat [gtab, gpush src2 0,
829 text " ; fmulp %st(0),", greg src1 1])
831 = pprG g (text "\t#GMUL-xxxcase2" $$
832 hcat [gtab, gpush src1 0,
833 text " ; fmulp %st(0),", greg src2 1])
835 = pprG g (hcat [gtab, gpush src1 0,
836 text " ; fmul ", greg src2 1, text ",%st(0)",
840 pprInstr g@(GSUB _ src1 src2 dst)
842 = pprG g (text "\t#GSUB-xxxcase1" $$
843 hcat [gtab, gpush src2 0,
844 text " ; fsubrp %st(0),", greg src1 1])
846 = pprG g (text "\t#GSUB-xxxcase2" $$
847 hcat [gtab, gpush src1 0,
848 text " ; fsubp %st(0),", greg src2 1])
850 = pprG g (hcat [gtab, gpush src1 0,
851 text " ; fsub ", greg src2 1, text ",%st(0)",
855 pprInstr g@(GDIV _ src1 src2 dst)
857 = pprG g (text "\t#GDIV-xxxcase1" $$
858 hcat [gtab, gpush src2 0,
859 text " ; fdivrp %st(0),", greg src1 1])
861 = pprG g (text "\t#GDIV-xxxcase2" $$
862 hcat [gtab, gpush src1 0,
863 text " ; fdivp %st(0),", greg src2 1])
865 = pprG g (hcat [gtab, gpush src1 0,
866 text " ; fdiv ", greg src2 1, text ",%st(0)",
871 = vcat [ ptext (sLit "\tffree %st(0) ;ffree %st(1) ;ffree %st(2) ;ffree %st(3)"),
872 ptext (sLit "\tffree %st(4) ;ffree %st(5) ;ffree %st(6) ;ffree %st(7)")
876 = panic "X86.Ppr.pprInstr: no match"
879 pprTrigOp :: String -> Bool -> CLabel -> CLabel -> Reg -> Reg -> Size -> Doc
880 pprTrigOp op -- fsin, fcos or fptan
881 isTan -- we need a couple of extra steps if we're doing tan
882 l1 l2 -- internal labels for us to use
884 = -- We'll be needing %eax later on
885 hcat [gtab, text "pushl %eax;"] $$
886 -- tan is going to use an extra space on the FP stack
887 (if isTan then hcat [gtab, text "ffree %st(6)"] else empty) $$
888 -- First put the value in %st(0) and try to apply the op to it
889 hcat [gpush src 0, text ("; " ++ op)] $$
890 -- Now look to see if C2 was set (overflow, |value| >= 2^63)
891 hcat [gtab, text "fnstsw %ax"] $$
892 hcat [gtab, text "test $0x400,%eax"] $$
893 -- If we were in bounds then jump to the end
894 hcat [gtab, text "je " <> pprCLabel_asm l1] $$
895 -- Otherwise we need to shrink the value. Start by
896 -- loading pi, doubleing it (by adding it to itself),
897 -- and then swapping pi with the value, so the value we
898 -- want to apply op to is in %st(0) again
899 hcat [gtab, text "ffree %st(7); fldpi"] $$
900 hcat [gtab, text "fadd %st(0),%st"] $$
901 hcat [gtab, text "fxch %st(1)"] $$
902 -- Now we have a loop in which we make the value smaller,
903 -- see if it's small enough, and loop if not
904 (pprCLabel_asm l2 <> char ':') $$
905 hcat [gtab, text "fprem1"] $$
906 -- My Debian libc uses fstsw here for the tan code, but I can't
907 -- see any reason why it should need to be different for tan.
908 hcat [gtab, text "fnstsw %ax"] $$
909 hcat [gtab, text "test $0x400,%eax"] $$
910 hcat [gtab, text "jne " <> pprCLabel_asm l2] $$
911 hcat [gtab, text "fstp %st(1)"] $$
912 hcat [gtab, text op] $$
913 (pprCLabel_asm l1 <> char ':') $$
914 -- Pop the 1.0 tan gave us
915 (if isTan then hcat [gtab, text "fstp %st(0)"] else empty) $$
917 hcat [gtab, text "popl %eax;"] $$
918 -- And finally make the result the right size
919 hcat [gtab, gcoerceto sz, gpop dst 1]
921 --------------------------
923 -- coerce %st(0) to the specified size
924 gcoerceto :: Size -> Doc
925 gcoerceto FF64 = empty
926 gcoerceto FF32 = empty --text "subl $4,%esp ; fstps (%esp) ; flds (%esp) ; addl $4,%esp ; "
927 gcoerceto _ = panic "X86.Ppr.gcoerceto: no match"
929 gpush :: Reg -> RegNo -> Doc
931 = hcat [text "ffree %st(7) ; fld ", greg reg offset]
934 gpop :: Reg -> RegNo -> Doc
936 = hcat [text "fstp ", greg reg offset]
938 greg :: Reg -> RegNo -> Doc
939 greg reg offset = text "%st(" <> int (gregno reg - 8+offset) <> char ')'
950 gregno :: Reg -> RegNo
951 gregno (RealReg i) = i
952 gregno _ = --pprPanic "gregno" (ppr other)
953 999 -- bogus; only needed for debug printing
955 pprG :: Instr -> Doc -> Doc
957 = (char '#' <> pprGInstr fake) $$ actual
960 pprGInstr :: Instr -> Doc
961 pprGInstr (GMOV src dst) = pprSizeRegReg (sLit "gmov") FF64 src dst
962 pprGInstr (GLD sz src dst) = pprSizeAddrReg (sLit "gld") sz src dst
963 pprGInstr (GST sz src dst) = pprSizeRegAddr (sLit "gst") sz src dst
965 pprGInstr (GLDZ dst) = pprSizeReg (sLit "gldz") FF64 dst
966 pprGInstr (GLD1 dst) = pprSizeReg (sLit "gld1") FF64 dst
968 pprGInstr (GFTOI src dst) = pprSizeSizeRegReg (sLit "gftoi") FF32 II32 src dst
969 pprGInstr (GDTOI src dst) = pprSizeSizeRegReg (sLit "gdtoi") FF64 II32 src dst
971 pprGInstr (GITOF src dst) = pprSizeSizeRegReg (sLit "gitof") II32 FF32 src dst
972 pprGInstr (GITOD src dst) = pprSizeSizeRegReg (sLit "gitod") II32 FF64 src dst
974 pprGInstr (GCMP co src dst) = pprCondRegReg (sLit "gcmp_") FF64 co src dst
975 pprGInstr (GABS sz src dst) = pprSizeRegReg (sLit "gabs") sz src dst
976 pprGInstr (GNEG sz src dst) = pprSizeRegReg (sLit "gneg") sz src dst
977 pprGInstr (GSQRT sz src dst) = pprSizeRegReg (sLit "gsqrt") sz src dst
978 pprGInstr (GSIN sz _ _ src dst) = pprSizeRegReg (sLit "gsin") sz src dst
979 pprGInstr (GCOS sz _ _ src dst) = pprSizeRegReg (sLit "gcos") sz src dst
980 pprGInstr (GTAN sz _ _ src dst) = pprSizeRegReg (sLit "gtan") sz src dst
982 pprGInstr (GADD sz src1 src2 dst) = pprSizeRegRegReg (sLit "gadd") sz src1 src2 dst
983 pprGInstr (GSUB sz src1 src2 dst) = pprSizeRegRegReg (sLit "gsub") sz src1 src2 dst
984 pprGInstr (GMUL sz src1 src2 dst) = pprSizeRegRegReg (sLit "gmul") sz src1 src2 dst
985 pprGInstr (GDIV sz src1 src2 dst) = pprSizeRegRegReg (sLit "gdiv") sz src1 src2 dst
987 pprGInstr _ = panic "X86.Ppr.pprGInstr: no match"
989 pprDollImm :: Imm -> Doc
990 pprDollImm i = ptext (sLit "$") <> pprImm i
993 pprOperand :: Size -> Operand -> Doc
994 pprOperand s (OpReg r) = pprReg s r
995 pprOperand _ (OpImm i) = pprDollImm i
996 pprOperand _ (OpAddr ea) = pprAddr ea
999 pprMnemonic_ :: LitString -> Doc
1001 char '\t' <> ptext name <> space
1004 pprMnemonic :: LitString -> Size -> Doc
1005 pprMnemonic name size =
1006 char '\t' <> ptext name <> pprSize size <> space
1009 pprSizeImmOp :: LitString -> Size -> Imm -> Operand -> Doc
1010 pprSizeImmOp name size imm op1
1012 pprMnemonic name size,
1020 pprSizeOp :: LitString -> Size -> Operand -> Doc
1021 pprSizeOp name size op1
1023 pprMnemonic name size,
1028 pprSizeOpOp :: LitString -> Size -> Operand -> Operand -> Doc
1029 pprSizeOpOp name size op1 op2
1031 pprMnemonic name size,
1032 pprOperand size op1,
1038 pprOpOp :: LitString -> Size -> Operand -> Operand -> Doc
1039 pprOpOp name size op1 op2
1042 pprOperand size op1,
1048 pprSizeReg :: LitString -> Size -> Reg -> Doc
1049 pprSizeReg name size reg1
1051 pprMnemonic name size,
1056 pprSizeRegReg :: LitString -> Size -> Reg -> Reg -> Doc
1057 pprSizeRegReg name size reg1 reg2
1059 pprMnemonic name size,
1066 pprRegReg :: LitString -> Reg -> Reg -> Doc
1067 pprRegReg name reg1 reg2
1070 pprReg archWordSize reg1,
1072 pprReg archWordSize reg2
1076 pprOpReg :: LitString -> Operand -> Reg -> Doc
1077 pprOpReg name op1 reg2
1080 pprOperand archWordSize op1,
1082 pprReg archWordSize reg2
1086 pprCondRegReg :: LitString -> Size -> Cond -> Reg -> Reg -> Doc
1087 pprCondRegReg name size cond reg1 reg2
1098 pprSizeSizeRegReg :: LitString -> Size -> Size -> Reg -> Reg -> Doc
1099 pprSizeSizeRegReg name size1 size2 reg1 reg2
1113 pprSizeRegRegReg :: LitString -> Size -> Reg -> Reg -> Reg -> Doc
1114 pprSizeRegRegReg name size reg1 reg2 reg3
1116 pprMnemonic name size,
1125 pprSizeAddrReg :: LitString -> Size -> AddrMode -> Reg -> Doc
1126 pprSizeAddrReg name size op dst
1128 pprMnemonic name size,
1135 pprSizeRegAddr :: LitString -> Size -> Reg -> AddrMode -> Doc
1136 pprSizeRegAddr name size src op
1138 pprMnemonic name size,
1145 pprShift :: LitString -> Size -> Operand -> Operand -> Doc
1146 pprShift name size src dest
1148 pprMnemonic name size,
1149 pprOperand II8 src, -- src is 8-bit sized
1151 pprOperand size dest
1155 pprSizeOpOpCoerce :: LitString -> Size -> Size -> Operand -> Operand -> Doc
1156 pprSizeOpOpCoerce name size1 size2 op1 op2
1157 = hcat [ char '\t', ptext name, pprSize size1, pprSize size2, space,
1158 pprOperand size1 op1,
1160 pprOperand size2 op2
1164 pprCondInstr :: LitString -> Cond -> Doc -> Doc
1165 pprCondInstr name cond arg
1166 = hcat [ char '\t', ptext name, pprCond cond, space, arg]