X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=ghc%2Fcompiler%2FnativeGen%2FPprMach.lhs;h=fae5f6cbb6a64ddece940bf6bff988763523b7f2;hb=b08b5149482e9d88b3a0f5098e7b118e6f00e115;hp=65a5edc092115f5bb6bb9c368e9cdb50c1a37be7;hpb=5cf27e8f1731c52fe63a5b9615f927484164c61b;p=ghc-hetmet.git diff --git a/ghc/compiler/nativeGen/PprMach.lhs b/ghc/compiler/nativeGen/PprMach.lhs index 65a5edc..fae5f6c 100644 --- a/ghc/compiler/nativeGen/PprMach.lhs +++ b/ghc/compiler/nativeGen/PprMach.lhs @@ -1,5 +1,5 @@ % -% (c) The AQUA Project, Glasgow University, 1996 +% (c) The AQUA Project, Glasgow University, 1996-1998 % \section[PprMach]{Pretty-printing assembly language} @@ -8,22 +8,38 @@ We start with the @pprXXX@s with some cross-platform commonality @pprInstr@. \begin{code} -#include "HsVersions.h" #include "nativeGen/NCG.h" -module PprMach ( pprInstr ) where +module PprMach ( pprInstr, pprSize, pprUserReg IF_OS_darwin(COMMA pprDyldSymbolStub, ) ) where -import Ubiq{-uitious-} +#include "HsVersions.h" import MachRegs -- may differ per-platform import MachMisc -import CLabel ( pprCLabel_asm, externallyVisibleCLabel ) -import CStrings ( charToC ) -import Maybes ( maybeToBool ) -import OrdList ( OrdList ) -import Stix ( CodeSegment(..), StixTree ) -import Unpretty -- all of it +import CLabel ( pprCLabel, externallyVisibleCLabel, labelDynamic ) +import Stix ( CodeSegment(..) ) +import Unique ( pprUnique ) +import Panic ( panic ) +import Pretty +import FastString +import qualified Outputable + +#if __GLASGOW_HASKELL__ >= 504 +import Data.Array.ST +import Data.Word ( Word8 ) +#else +import MutableArray +#endif + +import MONAD_ST + +import Char ( chr, ord ) +import Maybe ( isJust ) + +asmSDoc d = Outputable.withPprStyleDoc ( + Outputable.mkCodeStyle Outputable.AsmStyle) d +pprCLabel_asm l = asmSDoc (pprCLabel l) \end{code} %************************************************************************ @@ -35,148 +51,168 @@ import Unpretty -- all of it For x86, the way we print a register name depends on which bit of it we care about. Yurgh. \begin{code} -pprReg :: IF_ARCH_i386(Size ->,) Reg -> Unpretty +pprUserReg :: Reg -> Doc +pprUserReg = pprReg IF_ARCH_i386(L,) + +pprReg :: IF_ARCH_i386(Size ->,) Reg -> Doc pprReg IF_ARCH_i386(s,) r = case r of - FixedReg i -> ppr_reg_no IF_ARCH_i386(s,) i - MappedReg i -> ppr_reg_no IF_ARCH_i386(s,) i - other -> uppStr (show other) -- should only happen when debugging + RealReg i -> ppr_reg_no IF_ARCH_i386(s,) i + VirtualRegI u -> text "%vI_" <> asmSDoc (pprVRegUnique u) + VirtualRegF u -> text "%vF_" <> asmSDoc (pprVRegUnique u) where #if alpha_TARGET_ARCH - ppr_reg_no :: FAST_REG_NO -> Unpretty - ppr_reg_no i = uppPStr + ppr_reg_no :: Int -> Doc + ppr_reg_no i = ptext (case i of { - ILIT( 0) -> SLIT("$0"); ILIT( 1) -> SLIT("$1"); - ILIT( 2) -> SLIT("$2"); ILIT( 3) -> SLIT("$3"); - ILIT( 4) -> SLIT("$4"); ILIT( 5) -> SLIT("$5"); - ILIT( 6) -> SLIT("$6"); ILIT( 7) -> SLIT("$7"); - ILIT( 8) -> SLIT("$8"); ILIT( 9) -> SLIT("$9"); - ILIT(10) -> SLIT("$10"); ILIT(11) -> SLIT("$11"); - ILIT(12) -> SLIT("$12"); ILIT(13) -> SLIT("$13"); - ILIT(14) -> SLIT("$14"); ILIT(15) -> SLIT("$15"); - ILIT(16) -> SLIT("$16"); ILIT(17) -> SLIT("$17"); - ILIT(18) -> SLIT("$18"); ILIT(19) -> SLIT("$19"); - ILIT(20) -> SLIT("$20"); ILIT(21) -> SLIT("$21"); - ILIT(22) -> SLIT("$22"); ILIT(23) -> SLIT("$23"); - ILIT(24) -> SLIT("$24"); ILIT(25) -> SLIT("$25"); - ILIT(26) -> SLIT("$26"); ILIT(27) -> SLIT("$27"); - ILIT(28) -> SLIT("$28"); ILIT(29) -> SLIT("$29"); - ILIT(30) -> SLIT("$30"); ILIT(31) -> SLIT("$31"); - ILIT(32) -> SLIT("$f0"); ILIT(33) -> SLIT("$f1"); - ILIT(34) -> SLIT("$f2"); ILIT(35) -> SLIT("$f3"); - ILIT(36) -> SLIT("$f4"); ILIT(37) -> SLIT("$f5"); - ILIT(38) -> SLIT("$f6"); ILIT(39) -> SLIT("$f7"); - ILIT(40) -> SLIT("$f8"); ILIT(41) -> SLIT("$f9"); - ILIT(42) -> SLIT("$f10"); ILIT(43) -> SLIT("$f11"); - ILIT(44) -> SLIT("$f12"); ILIT(45) -> SLIT("$f13"); - ILIT(46) -> SLIT("$f14"); ILIT(47) -> SLIT("$f15"); - ILIT(48) -> SLIT("$f16"); ILIT(49) -> SLIT("$f17"); - ILIT(50) -> SLIT("$f18"); ILIT(51) -> SLIT("$f19"); - ILIT(52) -> SLIT("$f20"); ILIT(53) -> SLIT("$f21"); - ILIT(54) -> SLIT("$f22"); ILIT(55) -> SLIT("$f23"); - ILIT(56) -> SLIT("$f24"); ILIT(57) -> SLIT("$f25"); - ILIT(58) -> SLIT("$f26"); ILIT(59) -> SLIT("$f27"); - ILIT(60) -> SLIT("$f28"); ILIT(61) -> SLIT("$f29"); - ILIT(62) -> SLIT("$f30"); ILIT(63) -> SLIT("$f31"); - _ -> SLIT("very naughty alpha register") + 0 -> SLIT("$0"); 1 -> SLIT("$1"); + 2 -> SLIT("$2"); 3 -> SLIT("$3"); + 4 -> SLIT("$4"); 5 -> SLIT("$5"); + 6 -> SLIT("$6"); 7 -> SLIT("$7"); + 8 -> SLIT("$8"); 9 -> SLIT("$9"); + 10 -> SLIT("$10"); 11 -> SLIT("$11"); + 12 -> SLIT("$12"); 13 -> SLIT("$13"); + 14 -> SLIT("$14"); 15 -> SLIT("$15"); + 16 -> SLIT("$16"); 17 -> SLIT("$17"); + 18 -> SLIT("$18"); 19 -> SLIT("$19"); + 20 -> SLIT("$20"); 21 -> SLIT("$21"); + 22 -> SLIT("$22"); 23 -> SLIT("$23"); + 24 -> SLIT("$24"); 25 -> SLIT("$25"); + 26 -> SLIT("$26"); 27 -> SLIT("$27"); + 28 -> SLIT("$28"); 29 -> SLIT("$29"); + 30 -> SLIT("$30"); 31 -> SLIT("$31"); + 32 -> SLIT("$f0"); 33 -> SLIT("$f1"); + 34 -> SLIT("$f2"); 35 -> SLIT("$f3"); + 36 -> SLIT("$f4"); 37 -> SLIT("$f5"); + 38 -> SLIT("$f6"); 39 -> SLIT("$f7"); + 40 -> SLIT("$f8"); 41 -> SLIT("$f9"); + 42 -> SLIT("$f10"); 43 -> SLIT("$f11"); + 44 -> SLIT("$f12"); 45 -> SLIT("$f13"); + 46 -> SLIT("$f14"); 47 -> SLIT("$f15"); + 48 -> SLIT("$f16"); 49 -> SLIT("$f17"); + 50 -> SLIT("$f18"); 51 -> SLIT("$f19"); + 52 -> SLIT("$f20"); 53 -> SLIT("$f21"); + 54 -> SLIT("$f22"); 55 -> SLIT("$f23"); + 56 -> SLIT("$f24"); 57 -> SLIT("$f25"); + 58 -> SLIT("$f26"); 59 -> SLIT("$f27"); + 60 -> SLIT("$f28"); 61 -> SLIT("$f29"); + 62 -> SLIT("$f30"); 63 -> SLIT("$f31"); + _ -> SLIT("very naughty alpha register") }) #endif #if i386_TARGET_ARCH - ppr_reg_no :: Size -> FAST_REG_NO -> Unpretty - ppr_reg_no B i = uppPStr + ppr_reg_no :: Size -> Int -> Doc + ppr_reg_no B = ppr_reg_byte + ppr_reg_no Bu = ppr_reg_byte + ppr_reg_no W = ppr_reg_word + ppr_reg_no Wu = ppr_reg_word + ppr_reg_no _ = ppr_reg_long + + ppr_reg_byte i = ptext (case i of { - ILIT( 0) -> SLIT("%al"); ILIT( 1) -> SLIT("%bl"); - ILIT( 2) -> SLIT("%cl"); ILIT( 3) -> SLIT("%dl"); - _ -> SLIT("very naughty I386 byte register") + 0 -> SLIT("%al"); 1 -> SLIT("%bl"); + 2 -> SLIT("%cl"); 3 -> SLIT("%dl"); + _ -> SLIT("very naughty I386 byte register") }) - {- UNUSED: - ppr_reg_no HB i = uppPStr + ppr_reg_word i = ptext (case i of { - ILIT( 0) -> SLIT("%ah"); ILIT( 1) -> SLIT("%bh"); - ILIT( 2) -> SLIT("%ch"); ILIT( 3) -> SLIT("%dh"); - _ -> SLIT("very naughty I386 high byte register") + 0 -> SLIT("%ax"); 1 -> SLIT("%bx"); + 2 -> SLIT("%cx"); 3 -> SLIT("%dx"); + 4 -> SLIT("%si"); 5 -> SLIT("%di"); + 6 -> SLIT("%bp"); 7 -> SLIT("%sp"); + _ -> SLIT("very naughty I386 word register") }) - -} -{- UNUSED: - ppr_reg_no S i = uppPStr + ppr_reg_long i = ptext (case i of { - ILIT( 0) -> SLIT("%ax"); ILIT( 1) -> SLIT("%bx"); - ILIT( 2) -> SLIT("%cx"); ILIT( 3) -> SLIT("%dx"); - ILIT( 4) -> SLIT("%si"); ILIT( 5) -> SLIT("%di"); - ILIT( 6) -> SLIT("%bp"); ILIT( 7) -> SLIT("%sp"); - _ -> SLIT("very naughty I386 word register") + 0 -> SLIT("%eax"); 1 -> SLIT("%ebx"); + 2 -> SLIT("%ecx"); 3 -> SLIT("%edx"); + 4 -> SLIT("%esi"); 5 -> SLIT("%edi"); + 6 -> SLIT("%ebp"); 7 -> SLIT("%esp"); + 8 -> SLIT("%fake0"); 9 -> SLIT("%fake1"); + 10 -> SLIT("%fake2"); 11 -> SLIT("%fake3"); + 12 -> SLIT("%fake4"); 13 -> SLIT("%fake5"); + _ -> SLIT("very naughty I386 register") }) --} - - ppr_reg_no L i = uppPStr - (case i of { - ILIT( 0) -> SLIT("%eax"); ILIT( 1) -> SLIT("%ebx"); - ILIT( 2) -> SLIT("%ecx"); ILIT( 3) -> SLIT("%edx"); - ILIT( 4) -> SLIT("%esi"); ILIT( 5) -> SLIT("%edi"); - ILIT( 6) -> SLIT("%ebp"); ILIT( 7) -> SLIT("%esp"); - _ -> SLIT("very naughty I386 double word register") - }) - - ppr_reg_no F i = uppPStr - (case i of { - --ToDo: rm these (???) - ILIT( 8) -> SLIT("%st(0)"); ILIT( 9) -> SLIT("%st(1)"); - ILIT(10) -> SLIT("%st(2)"); ILIT(11) -> SLIT("%st(3)"); - ILIT(12) -> SLIT("%st(4)"); ILIT(13) -> SLIT("%st(5)"); - ILIT(14) -> SLIT("%st(6)"); ILIT(15) -> SLIT("%st(7)"); - _ -> SLIT("very naughty I386 float register") - }) - - ppr_reg_no DF i = uppPStr +#endif +#if sparc_TARGET_ARCH + ppr_reg_no :: Int -> Doc + ppr_reg_no i = ptext (case i of { - --ToDo: rm these (???) - ILIT( 8) -> SLIT("%st(0)"); ILIT( 9) -> SLIT("%st(1)"); - ILIT(10) -> SLIT("%st(2)"); ILIT(11) -> SLIT("%st(3)"); - ILIT(12) -> SLIT("%st(4)"); ILIT(13) -> SLIT("%st(5)"); - ILIT(14) -> SLIT("%st(6)"); ILIT(15) -> SLIT("%st(7)"); - _ -> SLIT("very naughty I386 float register") + 0 -> SLIT("%g0"); 1 -> SLIT("%g1"); + 2 -> SLIT("%g2"); 3 -> SLIT("%g3"); + 4 -> SLIT("%g4"); 5 -> SLIT("%g5"); + 6 -> SLIT("%g6"); 7 -> SLIT("%g7"); + 8 -> SLIT("%o0"); 9 -> SLIT("%o1"); + 10 -> SLIT("%o2"); 11 -> SLIT("%o3"); + 12 -> SLIT("%o4"); 13 -> SLIT("%o5"); + 14 -> SLIT("%o6"); 15 -> SLIT("%o7"); + 16 -> SLIT("%l0"); 17 -> SLIT("%l1"); + 18 -> SLIT("%l2"); 19 -> SLIT("%l3"); + 20 -> SLIT("%l4"); 21 -> SLIT("%l5"); + 22 -> SLIT("%l6"); 23 -> SLIT("%l7"); + 24 -> SLIT("%i0"); 25 -> SLIT("%i1"); + 26 -> SLIT("%i2"); 27 -> SLIT("%i3"); + 28 -> SLIT("%i4"); 29 -> SLIT("%i5"); + 30 -> SLIT("%i6"); 31 -> SLIT("%i7"); + 32 -> SLIT("%f0"); 33 -> SLIT("%f1"); + 34 -> SLIT("%f2"); 35 -> SLIT("%f3"); + 36 -> SLIT("%f4"); 37 -> SLIT("%f5"); + 38 -> SLIT("%f6"); 39 -> SLIT("%f7"); + 40 -> SLIT("%f8"); 41 -> SLIT("%f9"); + 42 -> SLIT("%f10"); 43 -> SLIT("%f11"); + 44 -> SLIT("%f12"); 45 -> SLIT("%f13"); + 46 -> SLIT("%f14"); 47 -> SLIT("%f15"); + 48 -> SLIT("%f16"); 49 -> SLIT("%f17"); + 50 -> SLIT("%f18"); 51 -> SLIT("%f19"); + 52 -> SLIT("%f20"); 53 -> SLIT("%f21"); + 54 -> SLIT("%f22"); 55 -> SLIT("%f23"); + 56 -> SLIT("%f24"); 57 -> SLIT("%f25"); + 58 -> SLIT("%f26"); 59 -> SLIT("%f27"); + 60 -> SLIT("%f28"); 61 -> SLIT("%f29"); + 62 -> SLIT("%f30"); 63 -> SLIT("%f31"); + _ -> SLIT("very naughty sparc register") }) #endif -#if sparc_TARGET_ARCH - ppr_reg_no :: FAST_REG_NO -> Unpretty - ppr_reg_no i = uppPStr +#if powerpc_TARGET_ARCH + ppr_reg_no :: Int -> Doc + ppr_reg_no i = ptext (case i of { - ILIT( 0) -> SLIT("%g0"); ILIT( 1) -> SLIT("%g1"); - ILIT( 2) -> SLIT("%g2"); ILIT( 3) -> SLIT("%g3"); - ILIT( 4) -> SLIT("%g4"); ILIT( 5) -> SLIT("%g5"); - ILIT( 6) -> SLIT("%g6"); ILIT( 7) -> SLIT("%g7"); - ILIT( 8) -> SLIT("%o0"); ILIT( 9) -> SLIT("%o1"); - ILIT(10) -> SLIT("%o2"); ILIT(11) -> SLIT("%o3"); - ILIT(12) -> SLIT("%o4"); ILIT(13) -> SLIT("%o5"); - ILIT(14) -> SLIT("%o6"); ILIT(15) -> SLIT("%o7"); - ILIT(16) -> SLIT("%l0"); ILIT(17) -> SLIT("%l1"); - ILIT(18) -> SLIT("%l2"); ILIT(19) -> SLIT("%l3"); - ILIT(20) -> SLIT("%l4"); ILIT(21) -> SLIT("%l5"); - ILIT(22) -> SLIT("%l6"); ILIT(23) -> SLIT("%l7"); - ILIT(24) -> SLIT("%i0"); ILIT(25) -> SLIT("%i1"); - ILIT(26) -> SLIT("%i2"); ILIT(27) -> SLIT("%i3"); - ILIT(28) -> SLIT("%i4"); ILIT(29) -> SLIT("%i5"); - ILIT(30) -> SLIT("%i6"); ILIT(31) -> SLIT("%i7"); - ILIT(32) -> SLIT("%f0"); ILIT(33) -> SLIT("%f1"); - ILIT(34) -> SLIT("%f2"); ILIT(35) -> SLIT("%f3"); - ILIT(36) -> SLIT("%f4"); ILIT(37) -> SLIT("%f5"); - ILIT(38) -> SLIT("%f6"); ILIT(39) -> SLIT("%f7"); - ILIT(40) -> SLIT("%f8"); ILIT(41) -> SLIT("%f9"); - ILIT(42) -> SLIT("%f10"); ILIT(43) -> SLIT("%f11"); - ILIT(44) -> SLIT("%f12"); ILIT(45) -> SLIT("%f13"); - ILIT(46) -> SLIT("%f14"); ILIT(47) -> SLIT("%f15"); - ILIT(48) -> SLIT("%f16"); ILIT(49) -> SLIT("%f17"); - ILIT(50) -> SLIT("%f18"); ILIT(51) -> SLIT("%f19"); - ILIT(52) -> SLIT("%f20"); ILIT(53) -> SLIT("%f21"); - ILIT(54) -> SLIT("%f22"); ILIT(55) -> SLIT("%f23"); - ILIT(56) -> SLIT("%f24"); ILIT(57) -> SLIT("%f25"); - ILIT(58) -> SLIT("%f26"); ILIT(59) -> SLIT("%f27"); - ILIT(60) -> SLIT("%f28"); ILIT(61) -> SLIT("%f29"); - ILIT(62) -> SLIT("%f30"); ILIT(63) -> SLIT("%f31"); - _ -> SLIT("very naughty sparc register") + 0 -> SLIT("r0"); 1 -> SLIT("r1"); + 2 -> SLIT("r2"); 3 -> SLIT("r3"); + 4 -> SLIT("r4"); 5 -> SLIT("r5"); + 6 -> SLIT("r6"); 7 -> SLIT("r7"); + 8 -> SLIT("r8"); 9 -> SLIT("r9"); + 10 -> SLIT("r10"); 11 -> SLIT("r11"); + 12 -> SLIT("r12"); 13 -> SLIT("r13"); + 14 -> SLIT("r14"); 15 -> SLIT("r15"); + 16 -> SLIT("r16"); 17 -> SLIT("r17"); + 18 -> SLIT("r18"); 19 -> SLIT("r19"); + 20 -> SLIT("r20"); 21 -> SLIT("r21"); + 22 -> SLIT("r22"); 23 -> SLIT("r23"); + 24 -> SLIT("r24"); 25 -> SLIT("r25"); + 26 -> SLIT("r26"); 27 -> SLIT("r27"); + 28 -> SLIT("r28"); 29 -> SLIT("r29"); + 30 -> SLIT("r30"); 31 -> SLIT("r31"); + 32 -> SLIT("f0"); 33 -> SLIT("f1"); + 34 -> SLIT("f2"); 35 -> SLIT("f3"); + 36 -> SLIT("f4"); 37 -> SLIT("f5"); + 38 -> SLIT("f6"); 39 -> SLIT("f7"); + 40 -> SLIT("f8"); 41 -> SLIT("f9"); + 42 -> SLIT("f10"); 43 -> SLIT("f11"); + 44 -> SLIT("f12"); 45 -> SLIT("f13"); + 46 -> SLIT("f14"); 47 -> SLIT("f15"); + 48 -> SLIT("f16"); 49 -> SLIT("f17"); + 50 -> SLIT("f18"); 51 -> SLIT("f19"); + 52 -> SLIT("f20"); 53 -> SLIT("f21"); + 54 -> SLIT("f22"); 55 -> SLIT("f23"); + 56 -> SLIT("f24"); 57 -> SLIT("f25"); + 58 -> SLIT("f26"); 59 -> SLIT("f27"); + 60 -> SLIT("f28"); 61 -> SLIT("f29"); + 62 -> SLIT("f30"); 63 -> SLIT("f31"); + _ -> SLIT("very naughty powerpc register") }) #endif \end{code} @@ -188,15 +224,15 @@ pprReg IF_ARCH_i386(s,) r %************************************************************************ \begin{code} -pprSize :: Size -> Unpretty +pprSize :: Size -> Doc -pprSize x = uppPStr (case x of +pprSize x = ptext (case x of #if alpha_TARGET_ARCH B -> SLIT("b") - BU -> SLIT("bu") + Bu -> SLIT("bu") -- W -> SLIT("w") UNUSED --- WU -> SLIT("wu") UNUSED --- L -> SLIT("l") UNUSED +-- Wu -> SLIT("wu") UNUSED + L -> SLIT("l") Q -> SLIT("q") -- FF -> SLIT("f") UNUSED -- DF -> SLIT("d") UNUSED @@ -205,23 +241,44 @@ pprSize x = uppPStr (case x of TF -> SLIT("t") #endif #if i386_TARGET_ARCH - B -> SLIT("b") --- HB -> SLIT("b") UNUSED --- S -> SLIT("w") UNUSED - L -> SLIT("l") - F -> SLIT("s") - DF -> SLIT("l") + B -> SLIT("b") + Bu -> SLIT("b") + W -> SLIT("w") + Wu -> SLIT("w") + L -> SLIT("l") + Lu -> SLIT("l") + F -> SLIT("s") + DF -> SLIT("l") + F80 -> SLIT("t") #endif #if sparc_TARGET_ARCH B -> SLIT("sb") --- HW -> SLIT("hw") UNUSED --- BU -> SLIT("ub") UNUSED --- HWU -> SLIT("uhw") UNUSED + Bu -> SLIT("ub") + H -> SLIT("sh") + Hu -> SLIT("uh") + W -> SLIT("") + F -> SLIT("") + DF -> SLIT("d") + ) +pprStSize :: Size -> Doc +pprStSize x = ptext (case x of + B -> SLIT("b") + Bu -> SLIT("b") + H -> SLIT("h") + Hu -> SLIT("h") W -> SLIT("") F -> SLIT("") --- D -> SLIT("d") UNUSED DF -> SLIT("d") #endif +#if powerpc_TARGET_ARCH + B -> SLIT("b") + Bu -> SLIT("b") + H -> SLIT("h") + Hu -> SLIT("h") + W -> SLIT("w") + F -> SLIT("fs") + DF -> SLIT("fd") +#endif ) \end{code} @@ -232,38 +289,47 @@ pprSize x = uppPStr (case x of %************************************************************************ \begin{code} -pprCond :: Cond -> Unpretty +pprCond :: Cond -> Doc -pprCond c = uppPStr (case c of { +pprCond c = ptext (case c of { #if alpha_TARGET_ARCH - EQ -> SLIT("eq"); - LT -> SLIT("lt"); + EQQ -> SLIT("eq"); + LTT -> SLIT("lt"); LE -> SLIT("le"); ULT -> SLIT("ult"); ULE -> SLIT("ule"); NE -> SLIT("ne"); - GT -> SLIT("gt"); + GTT -> SLIT("gt"); GE -> SLIT("ge") #endif #if i386_TARGET_ARCH GEU -> SLIT("ae"); LU -> SLIT("b"); - EQ -> SLIT("e"); GT -> SLIT("g"); + EQQ -> SLIT("e"); GTT -> SLIT("g"); GE -> SLIT("ge"); GU -> SLIT("a"); - LT -> SLIT("l"); LE -> SLIT("le"); + LTT -> SLIT("l"); LE -> SLIT("le"); LEU -> SLIT("be"); NE -> SLIT("ne"); NEG -> SLIT("s"); POS -> SLIT("ns"); + CARRY -> SLIT("c"); OFLO -> SLIT("o"); ALWAYS -> SLIT("mp") -- hack #endif #if sparc_TARGET_ARCH ALWAYS -> SLIT(""); NEVER -> SLIT("n"); GEU -> SLIT("geu"); LU -> SLIT("lu"); - EQ -> SLIT("e"); GT -> SLIT("g"); + EQQ -> SLIT("e"); GTT -> SLIT("g"); GE -> SLIT("ge"); GU -> SLIT("gu"); - LT -> SLIT("l"); LE -> SLIT("le"); + LTT -> SLIT("l"); LE -> SLIT("le"); LEU -> SLIT("leu"); NE -> SLIT("ne"); NEG -> SLIT("neg"); POS -> SLIT("pos"); VC -> SLIT("vc"); VS -> SLIT("vs") #endif +#if powerpc_TARGET_ARCH + ALWAYS -> SLIT(""); + EQQ -> SLIT("eq"); NE -> SLIT("ne"); + LTT -> SLIT("lt"); GE -> SLIT("ge"); + GTT -> SLIT("gt"); LE -> SLIT("le"); + LU -> SLIT("lt"); GEU -> SLIT("ge"); + GU -> SLIT("gt"); LEU -> SLIT("le"); +#endif }) \end{code} @@ -274,26 +340,46 @@ pprCond c = uppPStr (case c of { %************************************************************************ \begin{code} -pprImm :: Imm -> Unpretty - -pprImm (ImmInt i) = uppInt i -pprImm (ImmInteger i) = uppInteger i -pprImm (ImmCLbl l) = pprCLabel_asm l +pprImm :: Imm -> Doc + +pprImm (ImmInt i) = int i +pprImm (ImmInteger i) = integer i +pprImm (ImmCLbl l) = (if labelDynamic l then text "__imp_" else empty) + <> pprCLabel_asm l +pprImm (ImmIndex l i) = (if labelDynamic l then text "__imp_" else empty) + <> pprCLabel_asm l <> char '+' <> int i pprImm (ImmLit s) = s -pprImm (ImmLab s) | underscorePrefix = uppBeside (uppChar '_') s - | otherwise = s +pprImm (ImmLab dll s) = (if underscorePrefix then char '_' else empty) + <> (if dll then text "_imp__" else empty) + <> s #if sparc_TARGET_ARCH pprImm (LO i) - = uppBesides [ pp_lo, pprImm i, uppRparen ] + = hcat [ pp_lo, pprImm i, rparen ] where - pp_lo = uppPStr (_packCString (A# "%lo("#)) + pp_lo = text "%lo(" pprImm (HI i) - = uppBesides [ pp_hi, pprImm i, uppRparen ] + = hcat [ pp_hi, pprImm i, rparen ] where - pp_hi = uppPStr (_packCString (A# "%hi("#)) + pp_hi = text "%hi(" +#endif +#if powerpc_TARGET_ARCH +pprImm (LO i) + = hcat [ pp_lo, pprImm i, rparen ] + where + pp_lo = text "lo16(" + +pprImm (HI i) + = hcat [ pp_hi, pprImm i, rparen ] + where + pp_hi = text "hi16(" + +pprImm (HA i) + = hcat [ pp_ha, pprImm i, rparen ] + where + pp_ha = text "ha16(" #endif \end{code} @@ -304,69 +390,79 @@ pprImm (HI i) %************************************************************************ \begin{code} -pprAddr :: Addr -> Unpretty +pprAddr :: MachRegsAddr -> Doc #if alpha_TARGET_ARCH -pprAddr (AddrReg r) = uppParens (pprReg r) +pprAddr (AddrReg r) = parens (pprReg r) pprAddr (AddrImm i) = pprImm i pprAddr (AddrRegImm r1 i) - = uppBeside (pprImm i) (uppParens (pprReg r1)) + = (<>) (pprImm i) (parens (pprReg r1)) #endif ------------------- #if i386_TARGET_ARCH pprAddr (ImmAddr imm off) - = let - pp_imm = pprImm imm + = let pp_imm = pprImm imm in if (off == 0) then pp_imm else if (off < 0) then - uppBeside pp_imm (uppInt off) + pp_imm <> int off else - uppBesides [pp_imm, uppChar '+', uppInt off] + pp_imm <> char '+' <> int off -pprAddr (Addr base index displacement) +pprAddr (AddrBaseIndex base index displacement) = let pp_disp = ppr_disp displacement - pp_off p = uppBeside pp_disp (uppParens p) + pp_off p = pp_disp <> char '(' <> p <> char ')' pp_reg r = pprReg L r in case (base,index) of (Nothing, Nothing) -> pp_disp (Just b, Nothing) -> pp_off (pp_reg b) - (Nothing, Just (r,i)) -> pp_off (uppBesides [pp_reg r, uppComma, uppInt i]) - (Just b, Just (r,i)) -> pp_off (uppBesides [pp_reg b, uppComma, pp_reg r, uppComma, uppInt i]) + (Nothing, Just (r,i)) -> pp_off (pp_reg r <> comma <> int i) + (Just b, Just (r,i)) -> pp_off (pp_reg b <> comma <> pp_reg r + <> comma <> int i) where - ppr_disp (ImmInt 0) = uppNil + ppr_disp (ImmInt 0) = empty ppr_disp imm = pprImm imm #endif ------------------- #if sparc_TARGET_ARCH -pprAddr (AddrRegReg r1 (FixedReg ILIT(0))) = pprReg r1 +pprAddr (AddrRegReg r1 (RealReg 0)) = pprReg r1 pprAddr (AddrRegReg r1 r2) - = uppBesides [ pprReg r1, uppChar '+', pprReg r2 ] + = hcat [ pprReg r1, char '+', pprReg r2 ] pprAddr (AddrRegImm r1 (ImmInt i)) | i == 0 = pprReg r1 | not (fits13Bits i) = largeOffsetError i - | otherwise = uppBesides [ pprReg r1, pp_sign, uppInt i ] + | otherwise = hcat [ pprReg r1, pp_sign, int i ] where - pp_sign = if i > 0 then uppChar '+' else uppNil + pp_sign = if i > 0 then char '+' else empty pprAddr (AddrRegImm r1 (ImmInteger i)) | i == 0 = pprReg r1 | not (fits13Bits i) = largeOffsetError i - | otherwise = uppBesides [ pprReg r1, pp_sign, uppInteger i ] +------------------- + + | otherwise = hcat [ pprReg r1, pp_sign, integer i ] where - pp_sign = if i > 0 then uppChar '+' else uppNil + pp_sign = if i > 0 then char '+' else empty pprAddr (AddrRegImm r1 imm) - = uppBesides [ pprReg r1, uppChar '+', pprImm imm ] + = hcat [ pprReg r1, char '+', pprImm imm ] +#endif +#if powerpc_TARGET_ARCH +pprAddr (AddrRegReg r1 r2) + = error "PprMach.pprAddr (AddrRegReg) unimplemented" + +pprAddr (AddrRegImm r1 (ImmInt i)) = hcat [ int i, char '(', pprReg r1, char ')' ] +pprAddr (AddrRegImm r1 (ImmInteger i)) = hcat [ integer i, char '(', pprReg r1, char ')' ] +pprAddr (AddrRegImm r1 imm) = hcat [ pprImm imm, char '(', pprReg r1, char ')' ] #endif \end{code} @@ -377,94 +473,116 @@ pprAddr (AddrRegImm r1 imm) %************************************************************************ \begin{code} -pprInstr :: Instr -> Unpretty +pprInstr :: Instr -> Doc + +--pprInstr (COMMENT s) = empty -- nuke 'em +pprInstr (COMMENT s) + = IF_ARCH_alpha( ((<>) (ptext SLIT("\t# ")) (ftext s)) + ,IF_ARCH_sparc( ((<>) (ptext SLIT("! ")) (ftext s)) + ,IF_ARCH_i386( ((<>) (ptext SLIT("# ")) (ftext s)) + ,IF_ARCH_powerpc( ((<>) (ptext SLIT("; ")) (ftext s)) + ,)))) -pprInstr (COMMENT s) = uppNil -- nuke 'em ---alpha: = uppBeside (uppPStr SLIT("\t# ")) (uppPStr s) ---i386 : = uppBeside (uppPStr SLIT("# ")) (uppPStr s) ---sparc: = uppBeside (uppPStr SLIT("! ")) (uppPStr s) +pprInstr (DELTA d) + = pprInstr (COMMENT (mkFastString ("\tdelta = " ++ show d))) pprInstr (SEGMENT TextSegment) - = uppPStr - IF_ARCH_alpha(SLIT("\t.text\n\t.align 3") {-word boundary-} - ,IF_ARCH_sparc(SLIT("\t.text\n\t.align 4") {-word boundary-} - ,IF_ARCH_i386(SLIT(".text\n\t.align 2,0x90") {-needs per-OS variation!-} - ,))) + = IF_ARCH_alpha(ptext SLIT("\t.text\n\t.align 3") {-word boundary-} + ,IF_ARCH_sparc(ptext SLIT(".text\n\t.align 4") {-word boundary-} + ,IF_ARCH_i386((text ".text\n\t.align 4,0x90") {-needs per-OS variation!-} + ,IF_ARCH_powerpc(ptext SLIT(".text\n.align 2") + ,)))) pprInstr (SEGMENT DataSegment) - = uppPStr + = ptext + IF_ARCH_alpha(SLIT("\t.data\n\t.align 3") + ,IF_ARCH_sparc(SLIT(".data\n\t.align 8") {-<8 will break double constants -} + ,IF_ARCH_i386(SLIT(".data\n\t.align 4") + ,IF_ARCH_powerpc(SLIT(".data\n.align 2") + ,)))) + +pprInstr (SEGMENT RoDataSegment) + = ptext IF_ARCH_alpha(SLIT("\t.data\n\t.align 3") - ,IF_ARCH_sparc(SLIT("\t.data\n\t.align 8") {-<8 will break double constants -} - ,IF_ARCH_i386(SLIT(".data\n\t.align 2") - ,))) + ,IF_ARCH_sparc(SLIT(".data\n\t.align 8") {-<8 will break double constants -} + ,IF_ARCH_i386(SLIT(".section .rodata\n\t.align 4") + ,IF_ARCH_powerpc(SLIT(".const_data\n.align 2") + ,)))) pprInstr (LABEL clab) = let pp_lab = pprCLabel_asm clab in - uppBesides [ + hcat [ if not (externallyVisibleCLabel clab) then - uppNil + empty else - uppBesides [uppPStr + hcat [ptext IF_ARCH_alpha(SLIT("\t.globl\t") ,IF_ARCH_i386(SLIT(".globl ") - ,IF_ARCH_sparc(SLIT("\t.global\t") - ,))) - , pp_lab, uppChar '\n'], + ,IF_ARCH_sparc(SLIT(".global\t") + ,IF_ARCH_powerpc(SLIT(".globl ") + ,)))) + , pp_lab, char '\n'], pp_lab, - uppChar ':' + char ':' ] pprInstr (ASCII False{-no backslash conversion-} str) - = uppBesides [ uppStr "\t.asciz \"", uppStr str, uppChar '"' ] + = hcat [ ptext SLIT("\t.asciz "), char '\"', text str, char '"' ] pprInstr (ASCII True str) - = uppBeside (uppStr "\t.ascii \"") (asciify str 60) - where - asciify :: String -> Int -> Unpretty - - asciify [] _ = uppStr ("\\0\"") - asciify s n | n <= 0 = uppBeside (uppStr "\"\n\t.ascii \"") (asciify s 60) - asciify ('\\':cs) n = uppBeside (uppStr "\\\\") (asciify cs (n-1)) - asciify ('\"':cs) n = uppBeside (uppStr "\\\"") (asciify cs (n-1)) - asciify (c:cs) n | isPrint c = uppBeside (uppChar c) (asciify cs (n-1)) - asciify [c] _ = uppBeside (uppStr (charToC c)) (uppStr ("\\0\"")) - asciify (c:(cs@(d:_))) n - | isDigit d = uppBeside (uppStr (charToC c)) (asciify cs 0) - | otherwise = uppBeside (uppStr (charToC c)) (asciify cs (n-1)) + = vcat (map do1 (str ++ [chr 0])) + where + do1 :: Char -> Doc + do1 c = ptext SLIT("\t.byte\t0x") <> hshow (ord c) + + hshow :: Int -> Doc + hshow n | n >= 0 && n <= 255 + = char (tab !! (n `div` 16)) <> char (tab !! (n `mod` 16)) + tab = "0123456789ABCDEF" + pprInstr (DATA s xs) - = uppInterleave (uppChar '\n') - [uppBeside (uppPStr pp_size) (pprImm x) | x <- xs] - where - pp_size = case s of + = vcat (concatMap (ppr_item s) xs) + where + #if alpha_TARGET_ARCH - B -> SLIT("\t.byte\t") - BU -> SLIT("\t.byte\t") ---UNUSED: W -> SLIT("\t.word\t") ---UNUSED: WU -> SLIT("\t.word\t") ---UNUSED: L -> SLIT("\t.long\t") - Q -> SLIT("\t.quad\t") ---UNUSED: FF -> SLIT("\t.f_floating\t") ---UNUSED: DF -> SLIT("\t.d_floating\t") ---UNUSED: GF -> SLIT("\t.g_floating\t") ---UNUSED: SF -> SLIT("\t.s_floating\t") - TF -> SLIT("\t.t_floating\t") + ppr_item = error "ppr_item on Alpha" +#endif +#if sparc_TARGET_ARCH + -- copy n paste of x86 version + ppr_item B x = [ptext SLIT("\t.byte\t") <> pprImm x] + ppr_item W x = [ptext SLIT("\t.long\t") <> pprImm x] + ppr_item F (ImmFloat r) + = let bs = floatToBytes (fromRational r) + in map (\b -> ptext SLIT("\t.byte\t") <> pprImm (ImmInt b)) bs + ppr_item DF (ImmDouble r) + = let bs = doubleToBytes (fromRational r) + in map (\b -> ptext SLIT("\t.byte\t") <> pprImm (ImmInt b)) bs #endif #if i386_TARGET_ARCH - B -> SLIT("\t.byte\t") ---UNUSED: HB -> SLIT("\t.byte\t") ---UNUSED: S -> SLIT("\t.word\t") - L -> SLIT("\t.long\t") - F -> SLIT("\t.long\t") - DF -> SLIT("\t.double\t") + ppr_item B x = [ptext SLIT("\t.byte\t") <> pprImm x] + ppr_item L x = [ptext SLIT("\t.long\t") <> pprImm x] + ppr_item F (ImmFloat r) + = let bs = floatToBytes (fromRational r) + in map (\b -> ptext SLIT("\t.byte\t") <> pprImm (ImmInt b)) bs + ppr_item DF (ImmDouble r) + = let bs = doubleToBytes (fromRational r) + in map (\b -> ptext SLIT("\t.byte\t") <> pprImm (ImmInt b)) bs #endif -#if sparc_TARGET_ARCH - B -> SLIT("\t.byte\t") - BU -> SLIT("\t.byte\t") - W -> SLIT("\t.word\t") - DF -> SLIT("\t.double\t") +#if powerpc_TARGET_ARCH + ppr_item B x = [ptext SLIT("\t.byte\t") <> pprImm x] + ppr_item Bu x = [ptext SLIT("\t.byte\t") <> pprImm x] + ppr_item H x = [ptext SLIT("\t.byte\t") <> pprImm x] + ppr_item Hu x = [ptext SLIT("\t.byte\t") <> pprImm x] + ppr_item W x = [ptext SLIT("\t.long\t") <> pprImm x] + ppr_item F (ImmFloat r) + = let bs = floatToBytes (fromRational r) + in map (\b -> ptext SLIT("\t.byte\t") <> pprImm (ImmInt b)) bs + ppr_item DF (ImmDouble r) + = let bs = doubleToBytes (fromRational r) + in map (\b -> ptext SLIT("\t.byte\t") <> pprImm (ImmInt b)) bs #endif -- fall through to rest of (machine-specific) pprInstr... @@ -480,177 +598,177 @@ pprInstr (DATA s xs) #if alpha_TARGET_ARCH pprInstr (LD size reg addr) - = uppBesides [ - uppPStr SLIT("\tld"), + = hcat [ + ptext SLIT("\tld"), pprSize size, - uppChar '\t', + char '\t', pprReg reg, - uppComma, + comma, pprAddr addr ] pprInstr (LDA reg addr) - = uppBesides [ - uppPStr SLIT("\tlda\t"), + = hcat [ + ptext SLIT("\tlda\t"), pprReg reg, - uppComma, + comma, pprAddr addr ] pprInstr (LDAH reg addr) - = uppBesides [ - uppPStr SLIT("\tldah\t"), + = hcat [ + ptext SLIT("\tldah\t"), pprReg reg, - uppComma, + comma, pprAddr addr ] pprInstr (LDGP reg addr) - = uppBesides [ - uppPStr SLIT("\tldgp\t"), + = hcat [ + ptext SLIT("\tldgp\t"), pprReg reg, - uppComma, + comma, pprAddr addr ] pprInstr (LDI size reg imm) - = uppBesides [ - uppPStr SLIT("\tldi"), + = hcat [ + ptext SLIT("\tldi"), pprSize size, - uppChar '\t', + char '\t', pprReg reg, - uppComma, + comma, pprImm imm ] pprInstr (ST size reg addr) - = uppBesides [ - uppPStr SLIT("\tst"), + = hcat [ + ptext SLIT("\tst"), pprSize size, - uppChar '\t', + char '\t', pprReg reg, - uppComma, + comma, pprAddr addr ] pprInstr (CLR reg) - = uppBesides [ - uppPStr SLIT("\tclr\t"), + = hcat [ + ptext SLIT("\tclr\t"), pprReg reg ] pprInstr (ABS size ri reg) - = uppBesides [ - uppPStr SLIT("\tabs"), + = hcat [ + ptext SLIT("\tabs"), pprSize size, - uppChar '\t', + char '\t', pprRI ri, - uppComma, + comma, pprReg reg ] pprInstr (NEG size ov ri reg) - = uppBesides [ - uppPStr SLIT("\tneg"), + = hcat [ + ptext SLIT("\tneg"), pprSize size, - if ov then uppPStr SLIT("v\t") else uppChar '\t', + if ov then ptext SLIT("v\t") else char '\t', pprRI ri, - uppComma, + comma, pprReg reg ] pprInstr (ADD size ov reg1 ri reg2) - = uppBesides [ - uppPStr SLIT("\tadd"), + = hcat [ + ptext SLIT("\tadd"), pprSize size, - if ov then uppPStr SLIT("v\t") else uppChar '\t', + if ov then ptext SLIT("v\t") else char '\t', pprReg reg1, - uppComma, + comma, pprRI ri, - uppComma, + comma, pprReg reg2 ] pprInstr (SADD size scale reg1 ri reg2) - = uppBesides [ - uppPStr (case scale of {{-UNUSED:L -> SLIT("\ts4");-} Q -> SLIT("\ts8")}), - uppPStr SLIT("add"), + = hcat [ + ptext (case scale of {{-UNUSED:L -> SLIT("\ts4");-} Q -> SLIT("\ts8")}), + ptext SLIT("add"), pprSize size, - uppChar '\t', + char '\t', pprReg reg1, - uppComma, + comma, pprRI ri, - uppComma, + comma, pprReg reg2 ] pprInstr (SUB size ov reg1 ri reg2) - = uppBesides [ - uppPStr SLIT("\tsub"), + = hcat [ + ptext SLIT("\tsub"), pprSize size, - if ov then uppPStr SLIT("v\t") else uppChar '\t', + if ov then ptext SLIT("v\t") else char '\t', pprReg reg1, - uppComma, + comma, pprRI ri, - uppComma, + comma, pprReg reg2 ] pprInstr (SSUB size scale reg1 ri reg2) - = uppBesides [ - uppPStr (case scale of {{-UNUSED:L -> SLIT("\ts4");-} Q -> SLIT("\ts8")}), - uppPStr SLIT("sub"), + = hcat [ + ptext (case scale of {{-UNUSED:L -> SLIT("\ts4");-} Q -> SLIT("\ts8")}), + ptext SLIT("sub"), pprSize size, - uppChar '\t', + char '\t', pprReg reg1, - uppComma, + comma, pprRI ri, - uppComma, + comma, pprReg reg2 ] pprInstr (MUL size ov reg1 ri reg2) - = uppBesides [ - uppPStr SLIT("\tmul"), + = hcat [ + ptext SLIT("\tmul"), pprSize size, - if ov then uppPStr SLIT("v\t") else uppChar '\t', + if ov then ptext SLIT("v\t") else char '\t', pprReg reg1, - uppComma, + comma, pprRI ri, - uppComma, + comma, pprReg reg2 ] pprInstr (DIV size uns reg1 ri reg2) - = uppBesides [ - uppPStr SLIT("\tdiv"), + = hcat [ + ptext SLIT("\tdiv"), pprSize size, - if uns then uppPStr SLIT("u\t") else uppChar '\t', + if uns then ptext SLIT("u\t") else char '\t', pprReg reg1, - uppComma, + comma, pprRI ri, - uppComma, + comma, pprReg reg2 ] pprInstr (REM size uns reg1 ri reg2) - = uppBesides [ - uppPStr SLIT("\trem"), + = hcat [ + ptext SLIT("\trem"), pprSize size, - if uns then uppPStr SLIT("u\t") else uppChar '\t', + if uns then ptext SLIT("u\t") else char '\t', pprReg reg1, - uppComma, + comma, pprRI ri, - uppComma, + comma, pprReg reg2 ] pprInstr (NOT ri reg) - = uppBesides [ - uppPStr SLIT("\tnot"), - uppChar '\t', + = hcat [ + ptext SLIT("\tnot"), + char '\t', pprRI ri, - uppComma, + comma, pprReg reg ] @@ -668,41 +786,41 @@ pprInstr (SRA reg1 ri reg2) = pprRegRIReg SLIT("sra") reg1 ri reg2 pprInstr (ZAP reg1 ri reg2) = pprRegRIReg SLIT("zap") reg1 ri reg2 pprInstr (ZAPNOT reg1 ri reg2) = pprRegRIReg SLIT("zapnot") reg1 ri reg2 -pprInstr (NOP) = uppPStr SLIT("\tnop") +pprInstr (NOP) = ptext SLIT("\tnop") pprInstr (CMP cond reg1 ri reg2) - = uppBesides [ - uppPStr SLIT("\tcmp"), + = hcat [ + ptext SLIT("\tcmp"), pprCond cond, - uppChar '\t', + char '\t', pprReg reg1, - uppComma, + comma, pprRI ri, - uppComma, + comma, pprReg reg2 ] pprInstr (FCLR reg) - = uppBesides [ - uppPStr SLIT("\tfclr\t"), + = hcat [ + ptext SLIT("\tfclr\t"), pprReg reg ] pprInstr (FABS reg1 reg2) - = uppBesides [ - uppPStr SLIT("\tfabs\t"), + = hcat [ + ptext SLIT("\tfabs\t"), pprReg reg1, - uppComma, + comma, pprReg reg2 ] pprInstr (FNEG size reg1 reg2) - = uppBesides [ - uppPStr SLIT("\tneg"), + = hcat [ + ptext SLIT("\tneg"), pprSize size, - uppChar '\t', + char '\t', pprReg reg1, - uppComma, + comma, pprReg reg2 ] @@ -712,94 +830,94 @@ pprInstr (FMUL size reg1 reg2 reg3) = pprSizeRegRegReg SLIT("mul") size reg1 reg pprInstr (FSUB size reg1 reg2 reg3) = pprSizeRegRegReg SLIT("sub") size reg1 reg2 reg3 pprInstr (CVTxy size1 size2 reg1 reg2) - = uppBesides [ - uppPStr SLIT("\tcvt"), + = hcat [ + ptext SLIT("\tcvt"), pprSize size1, - case size2 of {Q -> uppPStr SLIT("qc"); _ -> pprSize size2}, - uppChar '\t', + case size2 of {Q -> ptext SLIT("qc"); _ -> pprSize size2}, + char '\t', pprReg reg1, - uppComma, + comma, pprReg reg2 ] pprInstr (FCMP size cond reg1 reg2 reg3) - = uppBesides [ - uppPStr SLIT("\tcmp"), + = hcat [ + ptext SLIT("\tcmp"), pprSize size, pprCond cond, - uppChar '\t', + char '\t', pprReg reg1, - uppComma, + comma, pprReg reg2, - uppComma, + comma, pprReg reg3 ] pprInstr (FMOV reg1 reg2) - = uppBesides [ - uppPStr SLIT("\tfmov\t"), + = hcat [ + ptext SLIT("\tfmov\t"), pprReg reg1, - uppComma, + comma, pprReg reg2 ] pprInstr (BI ALWAYS reg lab) = pprInstr (BR lab) -pprInstr (BI NEVER reg lab) = uppNil +pprInstr (BI NEVER reg lab) = empty pprInstr (BI cond reg lab) - = uppBesides [ - uppPStr SLIT("\tb"), + = hcat [ + ptext SLIT("\tb"), pprCond cond, - uppChar '\t', + char '\t', pprReg reg, - uppComma, + comma, pprImm lab ] pprInstr (BF cond reg lab) - = uppBesides [ - uppPStr SLIT("\tfb"), + = hcat [ + ptext SLIT("\tfb"), pprCond cond, - uppChar '\t', + char '\t', pprReg reg, - uppComma, + comma, pprImm lab ] pprInstr (BR lab) - = uppBeside (uppPStr SLIT("\tbr\t")) (pprImm lab) + = (<>) (ptext SLIT("\tbr\t")) (pprImm lab) pprInstr (JMP reg addr hint) - = uppBesides [ - uppPStr SLIT("\tjmp\t"), + = hcat [ + ptext SLIT("\tjmp\t"), pprReg reg, - uppComma, + comma, pprAddr addr, - uppComma, - uppInt hint + comma, + int hint ] pprInstr (BSR imm n) - = uppBeside (uppPStr SLIT("\tbsr\t")) (pprImm imm) + = (<>) (ptext SLIT("\tbsr\t")) (pprImm imm) pprInstr (JSR reg addr n) - = uppBesides [ - uppPStr SLIT("\tjsr\t"), + = hcat [ + ptext SLIT("\tjsr\t"), pprReg reg, - uppComma, + comma, pprAddr addr ] pprInstr (FUNBEGIN clab) - = uppBesides [ + = hcat [ if (externallyVisibleCLabel clab) then - uppBesides [uppPStr SLIT("\t.globl\t"), pp_lab, uppChar '\n'] + hcat [ptext SLIT("\t.globl\t"), pp_lab, char '\n'] else - uppNil, - uppPStr SLIT("\t.ent "), + empty, + ptext SLIT("\t.ent "), pp_lab, - uppChar '\n', + char '\n', pp_lab, pp_ldgp, pp_lab, @@ -807,46 +925,49 @@ pprInstr (FUNBEGIN clab) ] where pp_lab = pprCLabel_asm clab - pp_ldgp = uppPStr (_packCString (A# ":\n\tldgp $29,0($27)\n"#)) - pp_frame = uppPStr (_packCString (A# "..ng:\n\t.frame $30,4240,$26,0\n\t.prologue 1"#)) + + -- NEVER use commas within those string literals, cpp will ruin your day + pp_ldgp = hcat [ ptext SLIT(":\n\tldgp $29"), char ',', ptext SLIT("0($27)\n") ] + pp_frame = hcat [ ptext SLIT("..ng:\n\t.frame $30"), char ',', + ptext SLIT("4240"), char ',', + ptext SLIT("$26"), char ',', + ptext SLIT("0\n\t.prologue 1") ] pprInstr (FUNEND clab) - = uppBeside (uppPStr SLIT("\t.align 4\n\t.end ")) (pprCLabel_asm clab) + = (<>) (ptext SLIT("\t.align 4\n\t.end ")) (pprCLabel_asm clab) \end{code} Continue with Alpha-only printing bits and bobs: \begin{code} -pprRI :: RI -> Unpretty +pprRI :: RI -> Doc pprRI (RIReg r) = pprReg r pprRI (RIImm r) = pprImm r -pprRegRIReg :: FAST_STRING -> Reg -> RI -> Reg -> Unpretty - +pprRegRIReg :: LitString -> Reg -> RI -> Reg -> Doc pprRegRIReg name reg1 ri reg2 - = uppBesides [ - uppChar '\t', - uppPStr name, - uppChar '\t', + = hcat [ + char '\t', + ptext name, + char '\t', pprReg reg1, - uppComma, + comma, pprRI ri, - uppComma, + comma, pprReg reg2 ] -pprSizeRegRegReg :: FAST_STRING -> Size -> Reg -> Reg -> Reg -> Unpretty - +pprSizeRegRegReg :: LitString -> Size -> Reg -> Reg -> Reg -> Doc pprSizeRegRegReg name size reg1 reg2 reg3 - = uppBesides [ - uppChar '\t', - uppPStr name, + = hcat [ + char '\t', + ptext name, pprSize size, - uppChar '\t', + char '\t', pprReg reg1, - uppComma, + comma, pprReg reg2, - uppComma, + comma, pprReg reg3 ] @@ -862,23 +983,28 @@ pprSizeRegRegReg name size reg1 reg2 reg3 \begin{code} #if i386_TARGET_ARCH -pprInstr (MOV size (OpReg src) (OpReg dst)) -- hack +pprInstr v@(MOV size s@(OpReg src) d@(OpReg dst)) -- hack | src == dst - = uppPStr SLIT("") + = +#if 0 /* #ifdef DEBUG */ + (<>) (ptext SLIT("# warning: ")) (pprSizeOpOp SLIT("mov") size s d) +#else + empty +#endif pprInstr (MOV size src dst) = pprSizeOpOp SLIT("mov") size src dst -pprInstr (MOVZX size src dst) = pprSizeOpOpCoerce SLIT("movzx") L size src dst -pprInstr (MOVSX size src dst) = pprSizeOpOpCoerce SLIT("movxs") L size src dst +pprInstr (MOVZxL sizes src dst) = pprSizeOpOpCoerce SLIT("movz") sizes L src dst +pprInstr (MOVSxL sizes src dst) = pprSizeOpOpCoerce SLIT("movs") sizes L src dst -- here we do some patching, since the physical registers are only set late -- in the code generation. -pprInstr (LEA size (OpAddr (Addr src1@(Just reg1) (Just (reg2,1)) (ImmInt 0))) dst@(OpReg reg3)) +pprInstr (LEA size (OpAddr (AddrBaseIndex src1@(Just reg1) (Just (reg2,1)) (ImmInt 0))) dst@(OpReg reg3)) | reg1 == reg3 = pprSizeOpOp SLIT("add") size (OpReg reg2) dst -pprInstr (LEA size (OpAddr (Addr src1@(Just reg1) (Just (reg2,1)) (ImmInt 0))) dst@(OpReg reg3)) +pprInstr (LEA size (OpAddr (AddrBaseIndex src1@(Just reg1) (Just (reg2,1)) (ImmInt 0))) dst@(OpReg reg3)) | reg2 == reg3 = pprSizeOpOp SLIT("add") size (OpReg reg1) dst -pprInstr (LEA size (OpAddr (Addr src1@(Just reg1) Nothing displ)) dst@(OpReg reg3)) +pprInstr (LEA size (OpAddr (AddrBaseIndex src1@(Just reg1) Nothing displ)) dst@(OpReg reg3)) | reg1 == reg3 = pprInstr (ADD size (OpImm displ) dst) pprInstr (LEA size src dst) = pprSizeOpOp SLIT("lea") size src dst @@ -891,187 +1017,532 @@ pprInstr (ADD size src dst) = pprSizeOpOp SLIT("add") size src dst pprInstr (SUB size src dst) = pprSizeOpOp SLIT("sub") size src dst pprInstr (IMUL size op1 op2) = pprSizeOpOp SLIT("imul") size op1 op2 -pprInstr (IDIV size op) = pprSizeOp SLIT("idiv") size op + +{- A hack. The Intel documentation says that "The two and three + operand forms [of IMUL] may also be used with unsigned operands + because the lower half of the product is the same regardless if + (sic) the operands are signed or unsigned. The CF and OF flags, + however, cannot be used to determine if the upper half of the + result is non-zero." So there. +-} +pprInstr (MUL size op1 op2) = pprSizeOpOp SLIT("imul") size op1 op2 pprInstr (AND size src dst) = pprSizeOpOp SLIT("and") size src dst pprInstr (OR size src dst) = pprSizeOpOp SLIT("or") size src dst pprInstr (XOR size src dst) = pprSizeOpOp SLIT("xor") size src dst pprInstr (NOT size op) = pprSizeOp SLIT("not") size op pprInstr (NEGI size op) = pprSizeOp SLIT("neg") size op -pprInstr (SHL size imm dst) = pprSizeOpOp SLIT("shl") size imm dst -pprInstr (SAR size imm dst) = pprSizeOpOp SLIT("sar") size imm dst -pprInstr (SHR size imm dst) = pprSizeOpOp SLIT("shr") size imm dst + +pprInstr (SHL size imm dst) = pprSizeImmOp SLIT("shl") size imm dst +pprInstr (SAR size imm dst) = pprSizeImmOp SLIT("sar") size imm dst +pprInstr (SHR size imm dst) = pprSizeImmOp SLIT("shr") size imm dst +pprInstr (BT size imm src) = pprSizeImmOp SLIT("bt") size imm src pprInstr (CMP size src dst) = pprSizeOpOp SLIT("cmp") size src dst pprInstr (TEST size src dst) = pprSizeOpOp SLIT("test") size src dst pprInstr (PUSH size op) = pprSizeOp SLIT("push") size op pprInstr (POP size op) = pprSizeOp SLIT("pop") size op +pprInstr PUSHA = ptext SLIT("\tpushal") +pprInstr POPA = ptext SLIT("\tpopal") -pprInstr (NOP) = uppPStr SLIT("\tnop") -pprInstr (CLTD) = uppPStr SLIT("\tcltd") +pprInstr NOP = ptext SLIT("\tnop") +pprInstr CLTD = ptext SLIT("\tcltd") pprInstr (SETCC cond op) = pprCondInstr SLIT("set") cond (pprOperand B op) pprInstr (JXX cond lab) = pprCondInstr SLIT("j") cond (pprCLabel_asm lab) -pprInstr (JMP (OpImm imm)) = uppBeside (uppPStr SLIT("\tjmp ")) (pprImm imm) -pprInstr (JMP op) = uppBeside (uppPStr SLIT("\tjmp *")) (pprOperand L op) - -pprInstr (CALL imm) - = uppBesides [ uppPStr SLIT("\tcall "), pprImm imm ] - -pprInstr SAHF = uppPStr SLIT("\tsahf") -pprInstr FABS = uppPStr SLIT("\tfabs") - -pprInstr (FADD sz src@(OpAddr _)) - = uppBesides [uppPStr SLIT("\tfadd"), pprSize sz, uppSP, pprOperand sz src] -pprInstr (FADD sz src) - = uppPStr SLIT("\tfadd") -pprInstr FADDP - = uppPStr SLIT("\tfaddp") -pprInstr (FMUL sz src) - = uppBesides [uppPStr SLIT("\tfmul"), pprSize sz, uppSP, pprOperand sz src] -pprInstr FMULP - = uppPStr SLIT("\tfmulp") -pprInstr (FIADD size op) = pprSizeAddr SLIT("fiadd") size op -pprInstr FCHS = uppPStr SLIT("\tfchs") -pprInstr (FCOM size op) = pprSizeOp SLIT("fcom") size op -pprInstr FCOS = uppPStr SLIT("\tfcos") -pprInstr (FIDIV size op) = pprSizeAddr SLIT("fidiv") size op -pprInstr (FDIV sz src) - = uppBesides [uppPStr SLIT("\tfdiv"), pprSize sz, uppSP, pprOperand sz src] -pprInstr FDIVP - = uppPStr SLIT("\tfdivp") -pprInstr (FDIVR sz src) - = uppBesides [uppPStr SLIT("\tfdivr"), pprSize sz, uppSP, pprOperand sz src] -pprInstr FDIVRP - = uppPStr SLIT("\tfdivpr") -pprInstr (FIDIVR size op) = pprSizeAddr SLIT("fidivr") size op -pprInstr (FICOM size op) = pprSizeAddr SLIT("ficom") size op -pprInstr (FILD sz op reg) = pprSizeAddrReg SLIT("fild") sz op reg -pprInstr (FIST size op) = pprSizeAddr SLIT("fist") size op -pprInstr (FLD sz (OpImm (ImmCLbl src))) - = uppBesides [uppPStr SLIT("\tfld"),pprSize sz,uppSP,pprCLabel_asm src] -pprInstr (FLD sz src) - = uppBesides [uppPStr SLIT("\tfld"),pprSize sz,uppSP,pprOperand sz src] -pprInstr FLD1 = uppPStr SLIT("\tfld1") -pprInstr FLDZ = uppPStr SLIT("\tfldz") -pprInstr (FIMUL size op) = pprSizeAddr SLIT("fimul") size op -pprInstr FRNDINT = uppPStr SLIT("\tfrndint") -pprInstr FSIN = uppPStr SLIT("\tfsin") -pprInstr FSQRT = uppPStr SLIT("\tfsqrt") -pprInstr (FST sz dst) - = uppBesides [uppPStr SLIT("\tfst"), pprSize sz, uppSP, pprOperand sz dst] -pprInstr (FSTP sz dst) - = uppBesides [uppPStr SLIT("\tfstp"), pprSize sz, uppSP, pprOperand sz dst] -pprInstr (FISUB size op) = pprSizeAddr SLIT("fisub") size op -pprInstr (FSUB sz src) - = uppBesides [uppPStr SLIT("\tfsub"), pprSize sz, uppSP, pprOperand sz src] -pprInstr FSUBP - = uppPStr SLIT("\tfsubp") -pprInstr (FSUBR size src) - = pprSizeOp SLIT("fsubr") size src -pprInstr FSUBRP - = uppPStr SLIT("\tfsubpr") -pprInstr (FISUBR size op) - = pprSizeAddr SLIT("fisubr") size op -pprInstr FTST = uppPStr SLIT("\tftst") -pprInstr (FCOMP sz op) - = uppBesides [uppPStr SLIT("\tfcomp"), pprSize sz, uppSP, pprOperand sz op] -pprInstr FUCOMPP = uppPStr SLIT("\tfucompp") -pprInstr FXCH = uppPStr SLIT("\tfxch") -pprInstr FNSTSW = uppPStr SLIT("\tfnstsw %ax") -pprInstr FNOP = uppPStr SLIT("") +pprInstr (JMP dsts (OpImm imm)) = (<>) (ptext SLIT("\tjmp ")) (pprImm imm) +pprInstr (JMP dsts op) = (<>) (ptext SLIT("\tjmp *")) (pprOperand L op) +pprInstr (CALL (Left imm)) = (<>) (ptext SLIT("\tcall ")) (pprImm imm) +pprInstr (CALL (Right reg)) = (<>) (ptext SLIT("\tcall *")) (pprReg L reg) + +-- First bool indicates signedness; second whether quot or rem +pprInstr (IQUOT sz src dst) = pprInstr_quotRem True True sz src dst +pprInstr (IREM sz src dst) = pprInstr_quotRem True False sz src dst + +pprInstr (QUOT sz src dst) = pprInstr_quotRem False True sz src dst +pprInstr (REM sz src dst) = pprInstr_quotRem False False sz src dst + +pprInstr (IMUL64 sd_hi sd_lo) = pprInstr_imul64 sd_hi sd_lo + + +-- Simulating a flat register set on the x86 FP stack is tricky. +-- you have to free %st(7) before pushing anything on the FP reg stack +-- so as to preclude the possibility of a FP stack overflow exception. +pprInstr g@(GMOV src dst) + | src == dst + = empty + | otherwise + = pprG g (hcat [gtab, gpush src 0, gsemi, gpop dst 1]) + +-- GLD sz addr dst ==> FFREE %st(7) ; FLDsz addr ; FSTP (dst+1) +pprInstr g@(GLD sz addr dst) + = pprG g (hcat [gtab, text "ffree %st(7) ; fld", pprSize sz, gsp, + pprAddr addr, gsemi, gpop dst 1]) + +-- GST sz src addr ==> FFREE %st(7) ; FLD dst ; FSTPsz addr +pprInstr g@(GST sz src addr) + = pprG g (hcat [gtab, gpush src 0, gsemi, + text "fstp", pprSize sz, gsp, pprAddr addr]) + +pprInstr g@(GLDZ dst) + = pprG g (hcat [gtab, text "ffree %st(7) ; fldz ; ", gpop dst 1]) +pprInstr g@(GLD1 dst) + = pprG g (hcat [gtab, text "ffree %st(7) ; fld1 ; ", gpop dst 1]) + +pprInstr g@(GFTOI src dst) + = pprInstr (GDTOI src dst) +pprInstr g@(GDTOI src dst) + = pprG g (hcat [gtab, text "subl $4, %esp ; ", + gpush src 0, gsemi, text "fistpl 0(%esp) ; popl ", + pprReg L dst]) + +pprInstr g@(GITOF src dst) + = pprInstr (GITOD src dst) +pprInstr g@(GITOD src dst) + = pprG g (hcat [gtab, text "pushl ", pprReg L src, + text " ; ffree %st(7); fildl (%esp) ; ", + gpop dst 1, text " ; addl $4,%esp"]) + +{- Gruesome swamp follows. If you're unfortunate enough to have ventured + this far into the jungle AND you give a Rat's Ass (tm) what's going + on, here's the deal. Generate code to do a floating point comparison + of src1 and src2, of kind cond, and set the Zero flag if true. + + The complications are to do with handling NaNs correctly. We want the + property that if either argument is NaN, then the result of the + comparison is False ... except if we're comparing for inequality, + in which case the answer is True. + + Here's how the general (non-inequality) case works. As an + example, consider generating the an equality test: + + pushl %eax -- we need to mess with this + + fcomp and pop pushed src1 + -- Result of comparison is in FPU Status Register bits + -- C3 C2 and C0 + fstsw %ax -- Move FPU Status Reg to %ax + sahf -- move C3 C2 C0 from %ax to integer flag reg + -- now the serious magic begins + setpo %ah -- %ah = if comparable(neither arg was NaN) then 1 else 0 + sete %al -- %al = if arg1 == arg2 then 1 else 0 + andb %ah,%al -- %al &= %ah + -- so %al == 1 iff (comparable && same); else it holds 0 + decb %al -- %al == 0, ZeroFlag=1 iff (comparable && same); + else %al == 0xFF, ZeroFlag=0 + -- the zero flag is now set as we desire. + popl %eax + + The special case of inequality differs thusly: + + setpe %ah -- %ah = if incomparable(either arg was NaN) then 1 else 0 + setne %al -- %al = if arg1 /= arg2 then 1 else 0 + orb %ah,%al -- %al = if (incomparable || different) then 1 else 0 + decb %al -- if (incomparable || different) then (%al == 0, ZF=1) + else (%al == 0xFF, ZF=0) +-} +pprInstr g@(GCMP cond src1 src2) + | case cond of { NE -> True; other -> False } + = pprG g (vcat [ + hcat [gtab, text "pushl %eax ; ",gpush src1 0], + hcat [gtab, text "fcomp ", greg src2 1, + text "; fstsw %ax ; sahf ; setpe %ah"], + hcat [gtab, text "setne %al ; ", + text "orb %ah,%al ; decb %al ; popl %eax"] + ]) + | otherwise + = pprG g (vcat [ + hcat [gtab, text "pushl %eax ; ",gpush src1 0], + hcat [gtab, text "fcomp ", greg src2 1, + text "; fstsw %ax ; sahf ; setpo %ah"], + hcat [gtab, text "set", pprCond (fix_FP_cond cond), text " %al ; ", + text "andb %ah,%al ; decb %al ; popl %eax"] + ]) + where + {- On the 486, the flags set by FP compare are the unsigned ones! + (This looks like a HACK to me. WDP 96/03) + -} + fix_FP_cond :: Cond -> Cond + fix_FP_cond GE = GEU + fix_FP_cond GTT = GU + fix_FP_cond LTT = LU + fix_FP_cond LE = LEU + fix_FP_cond EQQ = EQQ + fix_FP_cond NE = NE + -- there should be no others + + +pprInstr g@(GABS sz src dst) + = pprG g (hcat [gtab, gpush src 0, text " ; fabs ; ", gpop dst 1]) +pprInstr g@(GNEG sz src dst) + = pprG g (hcat [gtab, gpush src 0, text " ; fchs ; ", gpop dst 1]) + +pprInstr g@(GSQRT sz src dst) + = pprG g (hcat [gtab, gpush src 0, text " ; fsqrt"] $$ + hcat [gtab, gcoerceto sz, gpop dst 1]) +pprInstr g@(GSIN sz src dst) + = pprG g (hcat [gtab, gpush src 0, text " ; fsin"] $$ + hcat [gtab, gcoerceto sz, gpop dst 1]) +pprInstr g@(GCOS sz src dst) + = pprG g (hcat [gtab, gpush src 0, text " ; fcos"] $$ + hcat [gtab, gcoerceto sz, gpop dst 1]) +pprInstr g@(GTAN sz src dst) + = pprG g (hcat [gtab, text "ffree %st(6) ; ", + gpush src 0, text " ; fptan ; ", + text " fstp %st(0)"] $$ + hcat [gtab, gcoerceto sz, gpop dst 1]) + +-- In the translations for GADD, GMUL, GSUB and GDIV, +-- the first two cases are mere optimisations. The otherwise clause +-- generates correct code under all circumstances. + +pprInstr g@(GADD sz src1 src2 dst) + | src1 == dst + = pprG g (text "\t#GADD-xxxcase1" $$ + hcat [gtab, gpush src2 0, + text " ; faddp %st(0),", greg src1 1]) + | src2 == dst + = pprG g (text "\t#GADD-xxxcase2" $$ + hcat [gtab, gpush src1 0, + text " ; faddp %st(0),", greg src2 1]) + | otherwise + = pprG g (hcat [gtab, gpush src1 0, + text " ; fadd ", greg src2 1, text ",%st(0)", + gsemi, gpop dst 1]) + + +pprInstr g@(GMUL sz src1 src2 dst) + | src1 == dst + = pprG g (text "\t#GMUL-xxxcase1" $$ + hcat [gtab, gpush src2 0, + text " ; fmulp %st(0),", greg src1 1]) + | src2 == dst + = pprG g (text "\t#GMUL-xxxcase2" $$ + hcat [gtab, gpush src1 0, + text " ; fmulp %st(0),", greg src2 1]) + | otherwise + = pprG g (hcat [gtab, gpush src1 0, + text " ; fmul ", greg src2 1, text ",%st(0)", + gsemi, gpop dst 1]) + + +pprInstr g@(GSUB sz src1 src2 dst) + | src1 == dst + = pprG g (text "\t#GSUB-xxxcase1" $$ + hcat [gtab, gpush src2 0, + text " ; fsubrp %st(0),", greg src1 1]) + | src2 == dst + = pprG g (text "\t#GSUB-xxxcase2" $$ + hcat [gtab, gpush src1 0, + text " ; fsubp %st(0),", greg src2 1]) + | otherwise + = pprG g (hcat [gtab, gpush src1 0, + text " ; fsub ", greg src2 1, text ",%st(0)", + gsemi, gpop dst 1]) + + +pprInstr g@(GDIV sz src1 src2 dst) + | src1 == dst + = pprG g (text "\t#GDIV-xxxcase1" $$ + hcat [gtab, gpush src2 0, + text " ; fdivrp %st(0),", greg src1 1]) + | src2 == dst + = pprG g (text "\t#GDIV-xxxcase2" $$ + hcat [gtab, gpush src1 0, + text " ; fdivp %st(0),", greg src2 1]) + | otherwise + = pprG g (hcat [gtab, gpush src1 0, + text " ; fdiv ", greg src2 1, text ",%st(0)", + gsemi, gpop dst 1]) + + +pprInstr GFREE + = vcat [ ptext SLIT("\tffree %st(0) ;ffree %st(1) ;ffree %st(2) ;ffree %st(3)"), + ptext SLIT("\tffree %st(4) ;ffree %st(5) ;ffree %st(6) ;ffree %st(7)") + ] + + +pprInstr_quotRem signed isQuot sz src dst + | case sz of L -> False; _ -> True + = panic "pprInstr_quotRem: dunno how to do non-32bit operands" + | otherwise + = vcat [ + (text "\t# BEGIN " <> fakeInsn), + (text "\tpushl $0; pushl %eax; pushl %edx; pushl " <> pprOperand sz src), + (text "\tmovl " <> pprOperand sz dst <> text ",%eax; " <> widen_to_64), + (x86op <> text " 0(%esp); movl " <> text resReg <> text ",12(%esp)"), + (text "\tpopl %edx; popl %edx; popl %eax; popl " <> pprOperand sz dst), + (text "\t# END " <> fakeInsn) + ] + where + widen_to_64 | signed = text "cltd" + | not signed = text "xorl %edx,%edx" + x86op = if signed then text "\tidivl" else text "\tdivl" + resReg = if isQuot then "%eax" else "%edx" + opStr | signed = if isQuot then "IQUOT" else "IREM" + | not signed = if isQuot then "QUOT" else "REM" + fakeInsn = text opStr <+> pprOperand sz src + <> char ',' <+> pprOperand sz dst + +-- Emit code to make hi_reg:lo_reg be the 64-bit product of hi_reg and lo_reg +pprInstr_imul64 hi_reg lo_reg + = let fakeInsn = text "imul64" <+> pp_hi_reg <> comma <+> pp_lo_reg + pp_hi_reg = pprReg L hi_reg + pp_lo_reg = pprReg L lo_reg + in + vcat [ + text "\t# BEGIN " <> fakeInsn, + text "\tpushl" <+> pp_hi_reg <> text" ; pushl" <+> pp_lo_reg, + text "\tpushl %eax ; pushl %edx", + text "\tmovl 12(%esp), %eax ; imull 8(%esp)", + text "\tmovl %edx, 12(%esp) ; movl %eax, 8(%esp)", + text "\tpopl %edx ; popl %eax", + text "\tpopl" <+> pp_lo_reg <> text " ; popl" <+> pp_hi_reg, + text "\t# END " <> fakeInsn + ] + + +-------------------------- + +-- coerce %st(0) to the specified size +gcoerceto DF = empty +gcoerceto F = empty --text "subl $4,%esp ; fstps (%esp) ; flds (%esp) ; addl $4,%esp ; " + +gpush reg offset + = hcat [text "ffree %st(7) ; fld ", greg reg offset] +gpop reg offset + = hcat [text "fstp ", greg reg offset] + +bogus = text "\tbogus" +greg reg offset = text "%st(" <> int (gregno reg - 8+offset) <> char ')' +gsemi = text " ; " +gtab = char '\t' +gsp = char ' ' + +gregno (RealReg i) = i +gregno other = --pprPanic "gregno" (ppr other) + 999 -- bogus; only needed for debug printing + +pprG :: Instr -> Doc -> Doc +pprG fake actual + = (char '#' <> pprGInstr fake) $$ actual + +pprGInstr (GMOV src dst) = pprSizeRegReg SLIT("gmov") DF src dst +pprGInstr (GLD sz src dst) = pprSizeAddrReg SLIT("gld") sz src dst +pprGInstr (GST sz src dst) = pprSizeRegAddr SLIT("gst") sz src dst + +pprGInstr (GLDZ dst) = pprSizeReg SLIT("gldz") DF dst +pprGInstr (GLD1 dst) = pprSizeReg SLIT("gld1") DF dst + +pprGInstr (GFTOI src dst) = pprSizeSizeRegReg SLIT("gftoi") F L src dst +pprGInstr (GDTOI src dst) = pprSizeSizeRegReg SLIT("gdtoi") DF L src dst + +pprGInstr (GITOF src dst) = pprSizeSizeRegReg SLIT("gitof") L F src dst +pprGInstr (GITOD src dst) = pprSizeSizeRegReg SLIT("gitod") L DF src dst + +pprGInstr (GCMP co src dst) = pprCondRegReg SLIT("gcmp_") DF co src dst +pprGInstr (GABS sz src dst) = pprSizeRegReg SLIT("gabs") sz src dst +pprGInstr (GNEG sz src dst) = pprSizeRegReg SLIT("gneg") sz src dst +pprGInstr (GSQRT sz src dst) = pprSizeRegReg SLIT("gsqrt") sz src dst +pprGInstr (GSIN sz src dst) = pprSizeRegReg SLIT("gsin") sz src dst +pprGInstr (GCOS sz src dst) = pprSizeRegReg SLIT("gcos") sz src dst +pprGInstr (GTAN sz src dst) = pprSizeRegReg SLIT("gtan") sz src dst + +pprGInstr (GADD sz src1 src2 dst) = pprSizeRegRegReg SLIT("gadd") sz src1 src2 dst +pprGInstr (GSUB sz src1 src2 dst) = pprSizeRegRegReg SLIT("gsub") sz src1 src2 dst +pprGInstr (GMUL sz src1 src2 dst) = pprSizeRegRegReg SLIT("gmul") sz src1 src2 dst +pprGInstr (GDIV sz src1 src2 dst) = pprSizeRegRegReg SLIT("gdiv") sz src1 src2 dst \end{code} Continue with I386-only printing bits and bobs: \begin{code} -pprDollImm :: Imm -> Unpretty +pprDollImm :: Imm -> Doc -pprDollImm i = uppBesides [ uppPStr SLIT("$"), pprImm i] +pprDollImm i = ptext SLIT("$") <> pprImm i -pprOperand :: Size -> Operand -> Unpretty -pprOperand s (OpReg r) = pprReg s r -pprOperand s (OpImm i) = pprDollImm i +pprOperand :: Size -> Operand -> Doc +pprOperand s (OpReg r) = pprReg s r +pprOperand s (OpImm i) = pprDollImm i pprOperand s (OpAddr ea) = pprAddr ea -pprSizeOp :: FAST_STRING -> Size -> Operand -> Unpretty +pprSizeImmOp :: LitString -> Size -> Imm -> Operand -> Doc +pprSizeImmOp name size imm op1 + = hcat [ + char '\t', + ptext name, + pprSize size, + space, + char '$', + pprImm imm, + comma, + pprOperand size op1 + ] + +pprSizeOp :: LitString -> Size -> Operand -> Doc pprSizeOp name size op1 - = uppBesides [ - uppChar '\t', - uppPStr name, + = hcat [ + char '\t', + ptext name, pprSize size, - uppSP, + space, pprOperand size op1 ] -pprSizeOpOp :: FAST_STRING -> Size -> Operand -> Operand -> Unpretty +pprSizeOpOp :: LitString -> Size -> Operand -> Operand -> Doc pprSizeOpOp name size op1 op2 - = uppBesides [ - uppChar '\t', - uppPStr name, + = hcat [ + char '\t', + ptext name, pprSize size, - uppSP, + space, pprOperand size op1, - uppComma, + comma, + pprOperand size op2 + ] + +pprSizeByteOpOp :: LitString -> Size -> Operand -> Operand -> Doc +pprSizeByteOpOp name size op1 op2 + = hcat [ + char '\t', + ptext name, + pprSize size, + space, + pprOperand B op1, + comma, pprOperand size op2 ] -pprSizeOpReg :: FAST_STRING -> Size -> Operand -> Reg -> Unpretty +pprSizeOpReg :: LitString -> Size -> Operand -> Reg -> Doc pprSizeOpReg name size op1 reg - = uppBesides [ - uppChar '\t', - uppPStr name, + = hcat [ + char '\t', + ptext name, pprSize size, - uppSP, + space, pprOperand size op1, - uppComma, + comma, pprReg size reg ] -pprSizeAddr :: FAST_STRING -> Size -> Addr -> Unpretty +pprSizeReg :: LitString -> Size -> Reg -> Doc +pprSizeReg name size reg1 + = hcat [ + char '\t', + ptext name, + pprSize size, + space, + pprReg size reg1 + ] + +pprSizeRegReg :: LitString -> Size -> Reg -> Reg -> Doc +pprSizeRegReg name size reg1 reg2 + = hcat [ + char '\t', + ptext name, + pprSize size, + space, + pprReg size reg1, + comma, + pprReg size reg2 + ] + +pprCondRegReg :: LitString -> Size -> Cond -> Reg -> Reg -> Doc +pprCondRegReg name size cond reg1 reg2 + = hcat [ + char '\t', + ptext name, + pprCond cond, + space, + pprReg size reg1, + comma, + pprReg size reg2 + ] + +pprSizeSizeRegReg :: LitString -> Size -> Size -> Reg -> Reg -> Doc +pprSizeSizeRegReg name size1 size2 reg1 reg2 + = hcat [ + char '\t', + ptext name, + pprSize size1, + pprSize size2, + space, + pprReg size1 reg1, + + comma, + pprReg size2 reg2 + ] + +pprSizeRegRegReg :: LitString -> Size -> Reg -> Reg -> Reg -> Doc +pprSizeRegRegReg name size reg1 reg2 reg3 + = hcat [ + char '\t', + ptext name, + pprSize size, + space, + pprReg size reg1, + comma, + pprReg size reg2, + comma, + pprReg size reg3 + ] + +pprSizeAddr :: LitString -> Size -> MachRegsAddr -> Doc pprSizeAddr name size op - = uppBesides [ - uppChar '\t', - uppPStr name, + = hcat [ + char '\t', + ptext name, pprSize size, - uppSP, + space, pprAddr op ] -pprSizeAddrReg :: FAST_STRING -> Size -> Addr -> Reg -> Unpretty +pprSizeAddrReg :: LitString -> Size -> MachRegsAddr -> Reg -> Doc pprSizeAddrReg name size op dst - = uppBesides [ - uppChar '\t', - uppPStr name, + = hcat [ + char '\t', + ptext name, pprSize size, - uppSP, + space, pprAddr op, - uppComma, + comma, pprReg size dst ] -pprOpOp :: FAST_STRING -> Size -> Operand -> Operand -> Unpretty +pprSizeRegAddr :: LitString -> Size -> Reg -> MachRegsAddr -> Doc +pprSizeRegAddr name size src op + = hcat [ + char '\t', + ptext name, + pprSize size, + space, + pprReg size src, + comma, + pprAddr op + ] + +pprOpOp :: LitString -> Size -> Operand -> Operand -> Doc pprOpOp name size op1 op2 - = uppBesides [ - uppChar '\t', - uppPStr name, uppSP, + = hcat [ + char '\t', + ptext name, space, pprOperand size op1, - uppComma, + comma, pprOperand size op2 ] -pprSizeOpOpCoerce :: FAST_STRING -> Size -> Size -> Operand -> Operand -> Unpretty +pprSizeOpOpCoerce :: LitString -> Size -> Size -> Operand -> Operand -> Doc pprSizeOpOpCoerce name size1 size2 op1 op2 - = uppBesides [ uppChar '\t', uppPStr name, uppSP, + = hcat [ char '\t', ptext name, pprSize size1, pprSize size2, space, pprOperand size1 op1, - uppComma, + comma, pprOperand size2 op2 ] -pprCondInstr :: FAST_STRING -> Cond -> Unpretty -> Unpretty +pprCondInstr :: LitString -> Cond -> Doc -> Doc pprCondInstr name cond arg - = uppBesides [ uppChar '\t', uppPStr name, pprCond cond, uppSP, arg] + = hcat [ char '\t', ptext name, pprCond cond, space, arg] #endif {-i386_TARGET_ARCH-} \end{code} @@ -1087,75 +1558,104 @@ pprCondInstr name cond arg -- a clumsy hack for now, to handle possible double alignment problems -pprInstr (LD DF addr reg) | maybeToBool off_addr - = uppBesides [ - pp_ld_lbracket, - pprAddr addr, - pp_rbracket_comma, - pprReg reg, +-- even clumsier, to allow for RegReg regs that show when doing indexed +-- reads (bytearrays). +-- + +-- Translate to the following: +-- add g1,g2,g1 +-- ld [g1],%fn +-- ld [g1+4],%f(n+1) +-- sub g1,g2,g1 -- to restore g1 +pprInstr (LD DF (AddrRegReg g1 g2) reg) + = vcat [ + hcat [ptext SLIT("\tadd\t"), pprReg g1,comma,pprReg g2,comma,pprReg g1], + hcat [pp_ld_lbracket, pprReg g1, pp_rbracket_comma, pprReg reg], + hcat [pp_ld_lbracket, pprReg g1, ptext SLIT("+4]"), comma, pprReg (fPair reg)], + hcat [ptext SLIT("\tsub\t"), pprReg g1,comma,pprReg g2,comma,pprReg g1] + ] - uppChar '\n', - pp_ld_lbracket, - pprAddr addr2, - pp_rbracket_comma, - pprReg (fPair reg) +-- Translate to +-- ld [addr],%fn +-- ld [addr+4],%f(n+1) +pprInstr (LD DF addr reg) | isJust off_addr + = vcat [ + hcat [pp_ld_lbracket, pprAddr addr, pp_rbracket_comma, pprReg reg], + hcat [pp_ld_lbracket, pprAddr addr2, pp_rbracket_comma,pprReg (fPair reg)] ] where off_addr = addrOffset addr 4 addr2 = case off_addr of Just x -> x + pprInstr (LD size addr reg) - = uppBesides [ - uppPStr SLIT("\tld"), - pprSize size, - uppChar '\t', - uppLbrack, - pprAddr addr, - pp_rbracket_comma, - pprReg reg + = hcat [ + ptext SLIT("\tld"), + pprSize size, + char '\t', + lbrack, + pprAddr addr, + pp_rbracket_comma, + pprReg reg ] -- The same clumsy hack as above -pprInstr (ST DF reg addr) | maybeToBool off_addr - = uppBesides [ - uppPStr SLIT("\tst\t"), - pprReg reg, - pp_comma_lbracket, - pprAddr addr, +-- Translate to the following: +-- add g1,g2,g1 +-- st %fn,[g1] +-- st %f(n+1),[g1+4] +-- sub g1,g2,g1 -- to restore g1 +pprInstr (ST DF reg (AddrRegReg g1 g2)) + = vcat [ + hcat [ptext SLIT("\tadd\t"), pprReg g1,comma,pprReg g2,comma,pprReg g1], + hcat [ptext SLIT("\tst\t"), pprReg reg, pp_comma_lbracket, + pprReg g1, rbrack], + hcat [ptext SLIT("\tst\t"), pprReg (fPair reg), pp_comma_lbracket, + pprReg g1, ptext SLIT("+4]")], + hcat [ptext SLIT("\tsub\t"), pprReg g1,comma,pprReg g2,comma,pprReg g1] + ] - uppPStr SLIT("]\n\tst\t"), - pprReg (fPair reg), - pp_comma_lbracket, - pprAddr addr2, - uppRbrack +-- Translate to +-- st %fn,[addr] +-- st %f(n+1),[addr+4] +pprInstr (ST DF reg addr) | isJust off_addr + = vcat [ + hcat [ptext SLIT("\tst\t"), pprReg reg, pp_comma_lbracket, + pprAddr addr, rbrack], + hcat [ptext SLIT("\tst\t"), pprReg (fPair reg), pp_comma_lbracket, + pprAddr addr2, rbrack] ] where off_addr = addrOffset addr 4 addr2 = case off_addr of Just x -> x +-- no distinction is made between signed and unsigned bytes on stores for the +-- Sparc opcodes (at least I cannot see any, and gas is nagging me --SOF), +-- so we call a special-purpose pprSize for ST.. + pprInstr (ST size reg addr) - = uppBesides [ - uppPStr SLIT("\tst"), - pprSize size, - uppChar '\t', - pprReg reg, - pp_comma_lbracket, - pprAddr addr, - uppRbrack + = hcat [ + ptext SLIT("\tst"), + pprStSize size, + char '\t', + pprReg reg, + pp_comma_lbracket, + pprAddr addr, + rbrack ] pprInstr (ADD x cc reg1 ri reg2) | not x && not cc && riZero ri - = uppBesides [ uppPStr SLIT("\tmov\t"), pprReg reg1, uppComma, pprReg reg2 ] + = hcat [ ptext SLIT("\tmov\t"), pprReg reg1, comma, pprReg reg2 ] | otherwise = pprRegRIReg (if x then SLIT("addx") else SLIT("add")) cc reg1 ri reg2 pprInstr (SUB x cc reg1 ri reg2) | not x && cc && reg2 == g0 - = uppBesides [ uppPStr SLIT("\tcmp\t"), pprReg reg1, uppComma, pprRI ri ] + = hcat [ ptext SLIT("\tcmp\t"), pprReg reg1, comma, pprRI ri ] | not x && not cc && riZero ri - = uppBesides [ uppPStr SLIT("\tmov\t"), pprReg reg1, uppComma, pprReg reg2 ] + = hcat [ ptext SLIT("\tmov\t"), pprReg reg1, comma, pprReg reg2 ] | otherwise = pprRegRIReg (if x then SLIT("subx") else SLIT("sub")) cc reg1 ri reg2 @@ -1164,7 +1664,10 @@ pprInstr (ANDN b reg1 ri reg2) = pprRegRIReg SLIT("andn") b reg1 ri reg2 pprInstr (OR b reg1 ri reg2) | not b && reg1 == g0 - = uppBesides [ uppPStr SLIT("\tmov\t"), pprRI ri, uppComma, pprReg reg2 ] + = let doit = hcat [ ptext SLIT("\tmov\t"), pprRI ri, comma, pprReg reg2 ] + in case ri of + RIReg rrr | rrr == reg2 -> empty + other -> doit | otherwise = pprRegRIReg SLIT("or") b reg1 ri reg2 @@ -1177,21 +1680,25 @@ pprInstr (SLL reg1 ri reg2) = pprRegRIReg SLIT("sll") False reg1 ri reg2 pprInstr (SRL reg1 ri reg2) = pprRegRIReg SLIT("srl") False reg1 ri reg2 pprInstr (SRA reg1 ri reg2) = pprRegRIReg SLIT("sra") False reg1 ri reg2 +pprInstr (RDY rd) = ptext SLIT("\trd\t%y,") <> pprReg rd +pprInstr (SMUL b reg1 ri reg2) = pprRegRIReg SLIT("smul") b reg1 ri reg2 +pprInstr (UMUL b reg1 ri reg2) = pprRegRIReg SLIT("umul") b reg1 ri reg2 + pprInstr (SETHI imm reg) - = uppBesides [ - uppPStr SLIT("\tsethi\t"), + = hcat [ + ptext SLIT("\tsethi\t"), pprImm imm, - uppComma, + comma, pprReg reg ] -pprInstr NOP = uppPStr SLIT("\tnop") +pprInstr NOP = ptext SLIT("\tnop") pprInstr (FABS F reg1 reg2) = pprSizeRegReg SLIT("fabs") F reg1 reg2 pprInstr (FABS DF reg1 reg2) - = uppBeside (pprSizeRegReg SLIT("fabs") F reg1 reg2) - (if (reg1 == reg2) then uppNil - else uppBeside (uppChar '\n') + = (<>) (pprSizeRegReg SLIT("fabs") F reg1 reg2) + (if (reg1 == reg2) then empty + else (<>) (char '\n') (pprSizeRegReg SLIT("fmov") F (fPair reg1) (fPair reg2))) pprInstr (FADD size reg1 reg2 reg3) @@ -1203,9 +1710,9 @@ pprInstr (FDIV size reg1 reg2 reg3) pprInstr (FMOV F reg1 reg2) = pprSizeRegReg SLIT("fmov") F reg1 reg2 pprInstr (FMOV DF reg1 reg2) - = uppBeside (pprSizeRegReg SLIT("fmov") F reg1 reg2) - (if (reg1 == reg2) then uppNil - else uppBeside (uppChar '\n') + = (<>) (pprSizeRegReg SLIT("fmov") F reg1 reg2) + (if (reg1 == reg2) then empty + else (<>) (char '\n') (pprSizeRegReg SLIT("fmov") F (fPair reg1) (fPair reg2))) pprInstr (FMUL size reg1 reg2 reg3) @@ -1213,114 +1720,457 @@ pprInstr (FMUL size reg1 reg2 reg3) pprInstr (FNEG F reg1 reg2) = pprSizeRegReg SLIT("fneg") F reg1 reg2 pprInstr (FNEG DF reg1 reg2) - = uppBeside (pprSizeRegReg SLIT("fneg") F reg1 reg2) - (if (reg1 == reg2) then uppNil - else uppBeside (uppChar '\n') + = (<>) (pprSizeRegReg SLIT("fneg") F reg1 reg2) + (if (reg1 == reg2) then empty + else (<>) (char '\n') (pprSizeRegReg SLIT("fmov") F (fPair reg1) (fPair reg2))) pprInstr (FSQRT size reg1 reg2) = pprSizeRegReg SLIT("fsqrt") size reg1 reg2 pprInstr (FSUB size reg1 reg2 reg3) = pprSizeRegRegReg SLIT("fsub") size reg1 reg2 reg3 pprInstr (FxTOy size1 size2 reg1 reg2) - = uppBesides [ - uppPStr SLIT("\tf"), - uppPStr + = hcat [ + ptext SLIT("\tf"), + ptext (case size1 of W -> SLIT("ito") F -> SLIT("sto") DF -> SLIT("dto")), - uppPStr + ptext (case size2 of W -> SLIT("i\t") F -> SLIT("s\t") DF -> SLIT("d\t")), - pprReg reg1, uppComma, pprReg reg2 + pprReg reg1, comma, pprReg reg2 ] pprInstr (BI cond b lab) - = uppBesides [ - uppPStr SLIT("\tb"), pprCond cond, - if b then pp_comma_a else uppNil, - uppChar '\t', + = hcat [ + ptext SLIT("\tb"), pprCond cond, + if b then pp_comma_a else empty, + char '\t', pprImm lab ] pprInstr (BF cond b lab) - = uppBesides [ - uppPStr SLIT("\tfb"), pprCond cond, - if b then pp_comma_a else uppNil, - uppChar '\t', + = hcat [ + ptext SLIT("\tfb"), pprCond cond, + if b then pp_comma_a else empty, + char '\t', pprImm lab ] -pprInstr (JMP addr) = uppBeside (uppPStr SLIT("\tjmp\t")) (pprAddr addr) +pprInstr (JMP dsts addr) = (<>) (ptext SLIT("\tjmp\t")) (pprAddr addr) -pprInstr (CALL imm n _) - = uppBesides [ uppPStr SLIT("\tcall\t"), pprImm imm, uppComma, uppInt n ] +pprInstr (CALL (Left imm) n _) + = hcat [ ptext SLIT("\tcall\t"), pprImm imm, comma, int n ] +pprInstr (CALL (Right reg) n _) + = hcat [ ptext SLIT("\tcall\t"), pprReg reg, comma, int n ] \end{code} Continue with SPARC-only printing bits and bobs: \begin{code} -pprRI :: RI -> Unpretty +pprRI :: RI -> Doc pprRI (RIReg r) = pprReg r pprRI (RIImm r) = pprImm r -pprSizeRegReg :: FAST_STRING -> Size -> Reg -> Reg -> Unpretty +pprSizeRegReg :: LitString -> Size -> Reg -> Reg -> Doc pprSizeRegReg name size reg1 reg2 - = uppBesides [ - uppChar '\t', - uppPStr name, + = hcat [ + char '\t', + ptext name, (case size of - F -> uppPStr SLIT("s\t") - DF -> uppPStr SLIT("d\t")), + F -> ptext SLIT("s\t") + DF -> ptext SLIT("d\t")), pprReg reg1, - uppComma, + comma, pprReg reg2 ] -pprSizeRegRegReg :: FAST_STRING -> Size -> Reg -> Reg -> Reg -> Unpretty +pprSizeRegRegReg :: LitString -> Size -> Reg -> Reg -> Reg -> Doc pprSizeRegRegReg name size reg1 reg2 reg3 - = uppBesides [ - uppChar '\t', - uppPStr name, + = hcat [ + char '\t', + ptext name, (case size of - F -> uppPStr SLIT("s\t") - DF -> uppPStr SLIT("d\t")), + F -> ptext SLIT("s\t") + DF -> ptext SLIT("d\t")), pprReg reg1, - uppComma, + comma, pprReg reg2, - uppComma, + comma, pprReg reg3 ] -pprRegRIReg :: FAST_STRING -> Bool -> Reg -> RI -> Reg -> Unpretty +pprRegRIReg :: LitString -> Bool -> Reg -> RI -> Reg -> Doc pprRegRIReg name b reg1 ri reg2 - = uppBesides [ - uppChar '\t', - uppPStr name, - if b then uppPStr SLIT("cc\t") else uppChar '\t', + = hcat [ + char '\t', + ptext name, + if b then ptext SLIT("cc\t") else char '\t', pprReg reg1, - uppComma, + comma, pprRI ri, - uppComma, + comma, pprReg reg2 ] -pprRIReg :: FAST_STRING -> Bool -> RI -> Reg -> Unpretty +pprRIReg :: LitString -> Bool -> RI -> Reg -> Doc pprRIReg name b ri reg1 - = uppBesides [ - uppChar '\t', - uppPStr name, - if b then uppPStr SLIT("cc\t") else uppChar '\t', + = hcat [ + char '\t', + ptext name, + if b then ptext SLIT("cc\t") else char '\t', pprRI ri, - uppComma, + comma, pprReg reg1 ] -pp_ld_lbracket = uppPStr (_packCString (A# "\tld\t["#)) -pp_rbracket_comma = uppPStr (_packCString (A# "],"#)) -pp_comma_lbracket = uppPStr (_packCString (A# ",["#)) -pp_comma_a = uppPStr (_packCString (A# ",a"#)) +pp_ld_lbracket = ptext SLIT("\tld\t[") +pp_rbracket_comma = text "]," +pp_comma_lbracket = text ",[" +pp_comma_a = text ",a" #endif {-sparc_TARGET_ARCH-} \end{code} + +%************************************************************************ +%* * +\subsubsection{@pprInstr@ for PowerPC} +%* * +%************************************************************************ + +\begin{code} +#if powerpc_TARGET_ARCH +pprInstr (LD sz reg addr) = hcat [ + char '\t', + ptext SLIT("l"), + ptext (case sz of + B -> SLIT("ba") + Bu -> SLIT("bz") + H -> SLIT("ha") + Hu -> SLIT("hz") + W -> SLIT("wz") + F -> SLIT("fs") + DF -> SLIT("fd")), + char '\t', + pprReg reg, + ptext SLIT(", "), + pprAddr addr + ] +pprInstr (ST sz reg addr) = hcat [ + char '\t', + ptext SLIT("st"), + pprSize sz, + char '\t', + pprReg reg, + ptext SLIT(", "), + pprAddr addr + ] +pprInstr (STU sz reg addr) = hcat [ + char '\t', + ptext SLIT("st"), + pprSize sz, + ptext SLIT("u\t"), + pprReg reg, + ptext SLIT(", "), + pprAddr addr + ] +pprInstr (LIS reg imm) = hcat [ + char '\t', + ptext SLIT("lis"), + char '\t', + pprReg reg, + ptext SLIT(", "), + pprImm imm + ] +pprInstr (LI reg imm) = hcat [ + char '\t', + ptext SLIT("li"), + char '\t', + pprReg reg, + ptext SLIT(", "), + pprImm imm + ] +pprInstr (MR reg1 reg2) + | reg1 == reg2 = empty + | otherwise = hcat [ + char '\t', + case regClass reg1 of + RcInteger -> ptext SLIT("mr") + _ -> ptext SLIT("fmr"), + char '\t', + pprReg reg1, + ptext SLIT(", "), + pprReg reg2 + ] +pprInstr (CMP sz reg ri) = hcat [ + char '\t', + op, + char '\t', + pprReg reg, + ptext SLIT(", "), + pprRI ri + ] + where + op = hcat [ + ptext SLIT("cmp"), + pprSize sz, + case ri of + RIReg _ -> empty + RIImm _ -> char 'i' + ] +pprInstr (CMPL sz reg ri) = hcat [ + char '\t', + op, + char '\t', + pprReg reg, + ptext SLIT(", "), + pprRI ri + ] + where + op = hcat [ + ptext SLIT("cmpl"), + pprSize sz, + case ri of + RIReg _ -> empty + RIImm _ -> char 'i' + ] +pprInstr (BCC cond lbl) = hcat [ + char '\t', + ptext SLIT("b"), + pprCond cond, + char '\t', + pprCLabel_asm lbl + ] + +pprInstr (MTCTR reg) = hcat [ + char '\t', + ptext SLIT("mtctr"), + char '\t', + pprReg reg + ] +pprInstr (BCTR _) = hcat [ + char '\t', + ptext SLIT("bctr") + ] +pprInstr (BL imm _) = hcat [ + char '\t', + ptext SLIT("bl"), + char '\t', + pprImm imm + ] +pprInstr (BCTRL _) = hcat [ + char '\t', + ptext SLIT("bctrl") + ] +pprInstr (ADD reg1 reg2 ri) = pprLogic SLIT("add") reg1 reg2 ri +pprInstr (SUBF reg1 reg2 reg3) = pprLogic SLIT("subf") reg1 reg2 (RIReg reg3) +pprInstr (MULLW reg1 reg2 ri@(RIReg _)) = pprLogic SLIT("mullw") reg1 reg2 ri +pprInstr (MULLW reg1 reg2 ri@(RIImm _)) = pprLogic SLIT("mull") reg1 reg2 ri +pprInstr (DIVW reg1 reg2 reg3) = pprLogic SLIT("divw") reg1 reg2 (RIReg reg3) +pprInstr (DIVWU reg1 reg2 reg3) = pprLogic SLIT("divwu") reg1 reg2 (RIReg reg3) + + -- for some reason, "andi" doesn't exist. + -- we'll use "andi." instead. +pprInstr (AND reg1 reg2 (RIImm imm)) = hcat [ + char '\t', + ptext SLIT("andi."), + char '\t', + pprReg reg1, + ptext SLIT(", "), + pprReg reg2, + ptext SLIT(", "), + pprImm imm + ] +pprInstr (AND reg1 reg2 ri) = pprLogic SLIT("and") reg1 reg2 ri + +pprInstr (OR reg1 reg2 ri) = pprLogic SLIT("or") reg1 reg2 ri +pprInstr (XOR reg1 reg2 ri) = pprLogic SLIT("xor") reg1 reg2 ri + +pprInstr (XORIS reg1 reg2 imm) = hcat [ + char '\t', + ptext SLIT("xoris"), + char '\t', + pprReg reg1, + ptext SLIT(", "), + pprReg reg2, + ptext SLIT(", "), + pprImm imm + ] + +pprInstr (SLW reg1 reg2 ri) = pprLogic SLIT("slw") reg1 reg2 ri +pprInstr (SRW reg1 reg2 ri) = pprLogic SLIT("srw") reg1 reg2 ri +pprInstr (SRAW reg1 reg2 ri) = pprLogic SLIT("sraw") reg1 reg2 ri +pprInstr (NEG reg1 reg2) = pprUnary SLIT("neg") reg1 reg2 +pprInstr (NOT reg1 reg2) = pprUnary SLIT("not") reg1 reg2 + +pprInstr (FADD sz reg1 reg2 reg3) = pprBinaryF SLIT("fadd") sz reg1 reg2 reg3 +pprInstr (FSUB sz reg1 reg2 reg3) = pprBinaryF SLIT("fsub") sz reg1 reg2 reg3 +pprInstr (FMUL sz reg1 reg2 reg3) = pprBinaryF SLIT("fmul") sz reg1 reg2 reg3 +pprInstr (FDIV sz reg1 reg2 reg3) = pprBinaryF SLIT("fdiv") sz reg1 reg2 reg3 +pprInstr (FNEG reg1 reg2) = pprUnary SLIT("fneg") reg1 reg2 + +pprInstr (FCMP reg1 reg2) = hcat [ + char '\t', + ptext SLIT("fcmpu\tcr0, "), + -- Note: we're using fcmpu, not fcmpo + -- The difference is with fcmpo, compare with NaN is an invalid operation. + -- We don't handle invalid fp ops, so we don't care + pprReg reg1, + ptext SLIT(", "), + pprReg reg2 + ] + +pprInstr (FCTIWZ reg1 reg2) = pprUnary SLIT("fctiwz") reg1 reg2 + +pprInstr _ = ptext SLIT("something") + +pprLogic op reg1 reg2 ri = hcat [ + char '\t', + ptext op, + case ri of + RIReg _ -> empty + RIImm _ -> char 'i', + char '\t', + pprReg reg1, + ptext SLIT(", "), + pprReg reg2, + ptext SLIT(", "), + pprRI ri + ] + +pprUnary op reg1 reg2 = hcat [ + char '\t', + ptext op, + char '\t', + pprReg reg1, + ptext SLIT(", "), + pprReg reg2 + ] + +pprBinaryF op sz reg1 reg2 reg3 = hcat [ + char '\t', + ptext op, + pprFSize sz, + char '\t', + pprReg reg1, + ptext SLIT(", "), + pprReg reg2, + ptext SLIT(", "), + pprReg reg3 + ] + +pprRI :: RI -> Doc +pprRI (RIReg r) = pprReg r +pprRI (RIImm r) = pprImm r + +pprFSize DF = empty +pprFSize F = char 's' + +{- + The Mach-O object file format used in Darwin/Mac OS X needs a so-called + "symbol stub" for every function that might be imported from a dynamic + library. + The stubs are always the same, and they are all output at the end of the + generated assembly (see AsmCodeGen.lhs), so we don't use the Instr datatype. + Instead, we just pretty-print it directly. +-} + +#if darwin_TARGET_OS +pprDyldSymbolStub fn = + vcat [ + ptext SLIT(".symbol_stub"), + ptext SLIT("L_") <> ftext fn <> ptext SLIT("$stub:"), + ptext SLIT("\t.indirect_symbol _") <> ftext fn, + ptext SLIT("\tlis r11,ha16(L_") <> ftext fn <> ptext SLIT("$lazy_ptr)"), + ptext SLIT("\tlwz r12,lo16(L_") <> ftext fn <> ptext SLIT("$lazy_ptr)(r11)"), + ptext SLIT("\tmtctr r12"), + ptext SLIT("\taddi r11,r11,lo16(L_") <> ftext fn <> ptext SLIT("$lazy_ptr)"), + ptext SLIT("\tbctr"), + ptext SLIT(".lazy_symbol_pointer"), + ptext SLIT("L_") <> ftext fn <> ptext SLIT("$lazy_ptr:"), + ptext SLIT("\t.indirect_symbol _") <> ftext fn, + ptext SLIT("\t.long dyld_stub_binding_helper") + ] +#endif + + +#endif {-powerpc_TARGET_ARCH-} +\end{code} + +\begin{code} +#if __GLASGOW_HASKELL__ >= 504 +newFloatArray :: (Int,Int) -> ST s (STUArray s Int Float) +newFloatArray = newArray_ + +newDoubleArray :: (Int,Int) -> ST s (STUArray s Int Double) +newDoubleArray = newArray_ + +castFloatToCharArray :: STUArray s Int Float -> ST s (STUArray s Int Word8) +castFloatToCharArray = castSTUArray + +castDoubleToCharArray :: STUArray s Int Double -> ST s (STUArray s Int Word8) +castDoubleToCharArray = castSTUArray + +writeFloatArray :: STUArray s Int Float -> Int -> Float -> ST s () +writeFloatArray = writeArray + +writeDoubleArray :: STUArray s Int Double -> Int -> Double -> ST s () +writeDoubleArray = writeArray + +readCharArray :: STUArray s Int Word8 -> Int -> ST s Char +readCharArray arr i = do + w <- readArray arr i + return $! (chr (fromIntegral w)) + +#else + +castFloatToCharArray :: MutableByteArray s t -> ST s (MutableByteArray s t) +castFloatToCharArray = return + +castDoubleToCharArray :: MutableByteArray s t -> ST s (MutableByteArray s t) + + +castDoubleToCharArray = return + +#endif + +-- floatToBytes and doubleToBytes convert to the host's byte +-- order. Providing that we're not cross-compiling for a +-- target with the opposite endianness, this should work ok +-- on all targets. + +-- ToDo: this stuff is very similar to the shenanigans in PprAbs, +-- could they be merged? + +floatToBytes :: Float -> [Int] +floatToBytes f + = runST (do + arr <- newFloatArray ((0::Int),3) + writeFloatArray arr 0 f + arr <- castFloatToCharArray arr + i0 <- readCharArray arr 0 + i1 <- readCharArray arr 1 + i2 <- readCharArray arr 2 + i3 <- readCharArray arr 3 + return (map ord [i0,i1,i2,i3]) + ) + +doubleToBytes :: Double -> [Int] +doubleToBytes d + = runST (do + arr <- newDoubleArray ((0::Int),7) + writeDoubleArray arr 0 d + arr <- castDoubleToCharArray arr + i0 <- readCharArray arr 0 + i1 <- readCharArray arr 1 + i2 <- readCharArray arr 2 + i3 <- readCharArray arr 3 + i4 <- readCharArray arr 4 + i5 <- readCharArray arr 5 + i6 <- readCharArray arr 6 + i7 <- readCharArray arr 7 + return (map ord [i0,i1,i2,i3,i4,i5,i6,i7]) + ) +\end{code}