Commit 89a3241f authored by Peter Trommler's avatar Peter Trommler 🥁 Committed by Ben Gamari

PPC NCG: Implement callish prim ops

Provide PowerPC optimised implementations of callish prim ops.

MO_?_QuotRem
The generic implementation of quotient remainder prim ops uses
a division and a remainder operation. There is no remainder on
PowerPC and so we need to implement remainder "by hand" which
results in a duplication of the divide operation when using the
generic code.

Avoid this duplication by implementing the prim op in the native
code generator.

MO_U_Mul2
Use PowerPC's instructions for long multiplication.

Addition and subtraction
Use PowerPC add/subtract with carry/overflow instructions

MO_Clz and MO_Ctz
Use PowerPC's CNTLZ instruction and implement count trailing
zeros using count leading zeros

MO_QuotRem2
Implement an algorithm given by Henry Warren in "Hacker's Delight"
using PowerPC divide instruction. TODO: Use long division instructions
when available (POWER7 and later).

Test Plan: validate on AIX and 32-bit Linux

Reviewers: simonmar, erikd, hvr, austin, bgamari

Reviewed By: erikd, hvr, bgamari

Subscribers: trofi, kgardas, thomie

Differential Revision: https://phabricator.haskell.org/D2973
parent 9373994a
......@@ -815,33 +815,41 @@ type GenericOp = [CmmFormal] -> [CmmActual] -> FCode ()
callishPrimOpSupported :: DynFlags -> PrimOp -> Either CallishMachOp GenericOp
callishPrimOpSupported dflags op
= case op of
IntQuotRemOp | ncg && x86ish -> Left (MO_S_QuotRem (wordWidth dflags))
IntQuotRemOp | ncg && (x86ish
|| ppc) -> Left (MO_S_QuotRem (wordWidth dflags))
| otherwise -> Right (genericIntQuotRemOp dflags)
WordQuotRemOp | ncg && x86ish -> Left (MO_U_QuotRem (wordWidth dflags))
WordQuotRemOp | ncg && (x86ish
|| ppc) -> Left (MO_U_QuotRem (wordWidth dflags))
| otherwise -> Right (genericWordQuotRemOp dflags)
WordQuotRem2Op | (ncg && x86ish)
WordQuotRem2Op | (ncg && (x86ish
|| ppc))
|| llvm -> Left (MO_U_QuotRem2 (wordWidth dflags))
| otherwise -> Right (genericWordQuotRem2Op dflags)
WordAdd2Op | (ncg && x86ish)
WordAdd2Op | (ncg && (x86ish
|| ppc))
|| llvm -> Left (MO_Add2 (wordWidth dflags))
| otherwise -> Right genericWordAdd2Op
WordSubCOp | (ncg && x86ish)
WordSubCOp | (ncg && (x86ish
|| ppc))
|| llvm -> Left (MO_SubWordC (wordWidth dflags))
| otherwise -> Right genericWordSubCOp
IntAddCOp | (ncg && x86ish)
IntAddCOp | (ncg && (x86ish
|| ppc))
|| llvm -> Left (MO_AddIntC (wordWidth dflags))
| otherwise -> Right genericIntAddCOp
IntSubCOp | (ncg && x86ish)
IntSubCOp | (ncg && (x86ish
|| ppc))
|| llvm -> Left (MO_SubIntC (wordWidth dflags))
| otherwise -> Right genericIntSubCOp
WordMul2Op | ncg && x86ish
WordMul2Op | ncg && (x86ish
|| ppc)
|| llvm -> Left (MO_U_Mul2 (wordWidth dflags))
| otherwise -> Right genericWordMul2Op
FloatFabsOp | (ncg && x86ish)
......@@ -863,6 +871,10 @@ callishPrimOpSupported dflags op
ArchX86 -> True
ArchX86_64 -> True
_ -> False
ppc = case platformArch (targetPlatform dflags) of
ArchPPC -> True
ArchPPC_64 _ -> True
_ -> False
genericIntQuotRemOp :: DynFlags -> GenericOp
genericIntQuotRemOp dflags [res_q, res_r] [arg_x, arg_y]
......
......@@ -521,7 +521,7 @@ pprGotDeclaration _ _ OSAIX
]
-- PPC 64 ELF v1needs a Table Of Contents (TOC) on Linux
-- PPC 64 ELF v1 needs a Table Of Contents (TOC) on Linux
pprGotDeclaration _ (ArchPPC_64 ELF_V1) OSLinux
= text ".section \".toc\",\"aw\""
-- In ELF v2 we also need to tell the assembler that we want ABI
......@@ -814,7 +814,8 @@ initializePicBase_ppc ArchPPC os picReg
fetchPC (BasicBlock bID insns) =
BasicBlock bID (PPC.FETCHPC picReg
: PPC.ADDIS picReg picReg (PPC.HA gotOffset)
: PPC.ADDI picReg picReg (PPC.LO gotOffset)
: PPC.ADD picReg picReg
(PPC.RIImm (PPC.LO gotOffset))
: PPC.MR PPC.r30 picReg
: insns)
......
This diff is collapsed.
......@@ -210,40 +210,34 @@ data Instr
| BCTRL [Reg]
| ADD Reg Reg RI -- dst, src1, src2
| ADDO Reg Reg Reg -- add and set overflow
| ADDC Reg Reg Reg -- (carrying) dst, src1, src2
| ADDE Reg Reg Reg -- (extend) dst, src1, src2
| ADDI Reg Reg Imm -- Add Immediate dst, src1, src2
| ADDE Reg Reg Reg -- (extended) dst, src1, src2
| ADDZE Reg Reg -- (to zero extended) dst, src
| ADDIS Reg Reg Imm -- Add Immediate Shifted dst, src1, src2
| SUBF Reg Reg Reg -- dst, src1, src2 ; dst = src2 - src1
| SUBFC Reg Reg Reg -- (carrying) dst, src1, src2 ; dst = src2 - src1
| SUBFE Reg Reg Reg -- (extend) dst, src1, src2 ; dst = src2 - src1
| MULLD Reg Reg RI
| MULLW Reg Reg RI
| DIVW Reg Reg Reg
| DIVD Reg Reg Reg
| DIVWU Reg Reg Reg
| DIVDU Reg Reg Reg
| MULLW_MayOflo Reg Reg Reg
-- dst = 1 if src1 * src2 overflows
-- pseudo-instruction; pretty-printed as:
-- mullwo. dst, src1, src2
| SUBFO Reg Reg Reg -- subtract from and set overflow
| SUBFC Reg Reg RI -- (carrying) dst, src1, src2 ;
-- dst = src2 - src1
| SUBFE Reg Reg Reg -- (extended) dst, src1, src2 ;
-- dst = src2 - src1
| MULL Format Reg Reg RI
| MULLO Format Reg Reg Reg -- multiply and set overflow
| MFOV Format Reg -- move overflow bit (1|33) to register
-- pseudo-instruction; pretty printed as
-- mfxer dst
-- rlwinm dst, dst, 2, 31,31
| MULLD_MayOflo Reg Reg Reg
-- dst = 1 if src1 * src2 overflows
-- pseudo-instruction; pretty-printed as:
-- mulldo. dst, src1, src2
-- mfxer dst
-- rlwinm dst, dst, 2, 31,31
-- extr[w|d]i dst, dst, 1, [1|33]
| MULHU Format Reg Reg Reg
| DIV Format Bool Reg Reg Reg
| AND Reg Reg RI -- dst, src1, src2
| ANDC Reg Reg Reg -- AND with complement, dst = src1 & ~ src2
| OR Reg Reg RI -- dst, src1, src2
| ORIS Reg Reg Imm -- OR Immediate Shifted dst, src1, src2
| XOR Reg Reg RI -- dst, src1, src2
| XORIS Reg Reg Imm -- XOR Immediate Shifted dst, src1, src2
| EXTS Format Reg Reg
| CNTLZ Format Reg Reg
| NEG Reg Reg
| NOT Reg Reg
......@@ -253,6 +247,7 @@ data Instr
| SRA Format Reg Reg RI -- shift right arithmetic
| RLWINM Reg Reg Int Int Int -- Rotate Left Word Immediate then AND with Mask
| CLRLI Format Reg Reg Int -- clear left immediate (extended mnemonic)
| CLRRI Format Reg Reg Int -- clear right immediate (extended mnemonic)
| FADD Format Reg Reg Reg
......@@ -275,9 +270,6 @@ data Instr
| MFLR Reg -- move from link register
| FETCHPC Reg -- pseudo-instruction:
-- bcl to next insn, mflr reg
| FETCHTOC Reg CLabel -- pseudo-instruction
-- add TOC offset to address in r12
-- print .localentry for label
| LWSYNC -- memory barrier
| NOP -- no operation, PowerPC 64 bit
-- needs this as place holder to
......@@ -313,36 +305,37 @@ ppc_regUsageOfInstr platform instr
BCTRL params -> usage (params, callClobberedRegs platform)
ADD reg1 reg2 ri -> usage (reg2 : regRI ri, [reg1])
ADDO reg1 reg2 reg3 -> usage ([reg2,reg3], [reg1])
ADDC reg1 reg2 reg3 -> usage ([reg2,reg3], [reg1])
ADDE reg1 reg2 reg3 -> usage ([reg2,reg3], [reg1])
ADDI reg1 reg2 _ -> usage ([reg2], [reg1])
ADDZE reg1 reg2 -> usage ([reg2], [reg1])
ADDIS reg1 reg2 _ -> usage ([reg2], [reg1])
SUBF reg1 reg2 reg3 -> usage ([reg2,reg3], [reg1])
SUBFC reg1 reg2 reg3 -> usage ([reg2,reg3], [reg1])
SUBFO reg1 reg2 reg3 -> usage ([reg2,reg3], [reg1])
SUBFC reg1 reg2 ri -> usage (reg2 : regRI ri, [reg1])
SUBFE reg1 reg2 reg3 -> usage ([reg2,reg3], [reg1])
MULLD reg1 reg2 ri -> usage (reg2 : regRI ri, [reg1])
MULLW reg1 reg2 ri -> usage (reg2 : regRI ri, [reg1])
DIVW reg1 reg2 reg3 -> usage ([reg2,reg3], [reg1])
DIVD reg1 reg2 reg3 -> usage ([reg2,reg3], [reg1])
DIVWU reg1 reg2 reg3 -> usage ([reg2,reg3], [reg1])
DIVDU reg1 reg2 reg3 -> usage ([reg2,reg3], [reg1])
MULLW_MayOflo reg1 reg2 reg3
-> usage ([reg2,reg3], [reg1])
MULLD_MayOflo reg1 reg2 reg3
-> usage ([reg2,reg3], [reg1])
MULL _ reg1 reg2 ri -> usage (reg2 : regRI ri, [reg1])
MULLO _ reg1 reg2 reg3 -> usage ([reg2,reg3], [reg1])
MFOV _ reg -> usage ([], [reg])
MULHU _ reg1 reg2 reg3 -> usage ([reg2,reg3], [reg1])
DIV _ _ reg1 reg2 reg3
-> usage ([reg2,reg3], [reg1])
AND reg1 reg2 ri -> usage (reg2 : regRI ri, [reg1])
ANDC reg1 reg2 reg3 -> usage ([reg2,reg3], [reg1])
OR reg1 reg2 ri -> usage (reg2 : regRI ri, [reg1])
ORIS reg1 reg2 _ -> usage ([reg2], [reg1])
XOR reg1 reg2 ri -> usage (reg2 : regRI ri, [reg1])
XORIS reg1 reg2 _ -> usage ([reg2], [reg1])
EXTS _ reg1 reg2 -> usage ([reg2], [reg1])
CNTLZ _ reg1 reg2 -> usage ([reg2], [reg1])
NEG reg1 reg2 -> usage ([reg2], [reg1])
NOT reg1 reg2 -> usage ([reg2], [reg1])
SL _ reg1 reg2 ri -> usage (reg2 : regRI ri, [reg1])
SR _ reg1 reg2 ri -> usage (reg2 : regRI ri, [reg1])
SRA _ reg1 reg2 ri -> usage (reg2 : regRI ri, [reg1])
RLWINM reg1 reg2 _ _ _ -> usage ([reg2], [reg1])
CLRLI _ reg1 reg2 _ -> usage ([reg2], [reg1])
CLRRI _ reg1 reg2 _ -> usage ([reg2], [reg1])
FADD _ r1 r2 r3 -> usage ([r2,r3], [r1])
......@@ -358,7 +351,6 @@ ppc_regUsageOfInstr platform instr
MFCR reg -> usage ([], [reg])
MFLR reg -> usage ([], [reg])
FETCHPC reg -> usage ([], [reg])
FETCHTOC reg _ -> usage ([], [reg])
UPDATE_SP _ _ -> usage ([], [sp])
_ -> noUsage
where
......@@ -401,29 +393,33 @@ ppc_patchRegsOfInstr instr env
BL imm argRegs -> BL imm argRegs -- argument regs
BCTRL argRegs -> BCTRL argRegs -- cannot be remapped
ADD reg1 reg2 ri -> ADD (env reg1) (env reg2) (fixRI ri)
ADDO reg1 reg2 reg3 -> ADDO (env reg1) (env reg2) (env reg3)
ADDC reg1 reg2 reg3 -> ADDC (env reg1) (env reg2) (env reg3)
ADDE reg1 reg2 reg3 -> ADDE (env reg1) (env reg2) (env reg3)
ADDI reg1 reg2 imm -> ADDI (env reg1) (env reg2) imm
ADDZE reg1 reg2 -> ADDZE (env reg1) (env reg2)
ADDIS reg1 reg2 imm -> ADDIS (env reg1) (env reg2) imm
SUBF reg1 reg2 reg3 -> SUBF (env reg1) (env reg2) (env reg3)
SUBFC reg1 reg2 reg3 -> SUBFC (env reg1) (env reg2) (env reg3)
SUBFO reg1 reg2 reg3 -> SUBFO (env reg1) (env reg2) (env reg3)
SUBFC reg1 reg2 ri -> SUBFC (env reg1) (env reg2) (fixRI ri)
SUBFE reg1 reg2 reg3 -> SUBFE (env reg1) (env reg2) (env reg3)
MULLD reg1 reg2 ri -> MULLD (env reg1) (env reg2) (fixRI ri)
MULLW reg1 reg2 ri -> MULLW (env reg1) (env reg2) (fixRI ri)
DIVW reg1 reg2 reg3 -> DIVW (env reg1) (env reg2) (env reg3)
DIVD reg1 reg2 reg3 -> DIVD (env reg1) (env reg2) (env reg3)
DIVWU reg1 reg2 reg3 -> DIVWU (env reg1) (env reg2) (env reg3)
DIVDU reg1 reg2 reg3 -> DIVDU (env reg1) (env reg2) (env reg3)
MULLW_MayOflo reg1 reg2 reg3
-> MULLW_MayOflo (env reg1) (env reg2) (env reg3)
MULLD_MayOflo reg1 reg2 reg3
-> MULLD_MayOflo (env reg1) (env reg2) (env reg3)
MULL fmt reg1 reg2 ri
-> MULL fmt (env reg1) (env reg2) (fixRI ri)
MULLO fmt reg1 reg2 reg3
-> MULLO fmt (env reg1) (env reg2) (env reg3)
MFOV fmt reg -> MFOV fmt (env reg)
MULHU fmt reg1 reg2 reg3
-> MULHU fmt (env reg1) (env reg2) (env reg3)
DIV fmt sgn reg1 reg2 reg3
-> DIV fmt sgn (env reg1) (env reg2) (env reg3)
AND reg1 reg2 ri -> AND (env reg1) (env reg2) (fixRI ri)
ANDC reg1 reg2 reg3 -> ANDC (env reg1) (env reg2) (env reg3)
OR reg1 reg2 ri -> OR (env reg1) (env reg2) (fixRI ri)
ORIS reg1 reg2 imm -> ORIS (env reg1) (env reg2) imm
XOR reg1 reg2 ri -> XOR (env reg1) (env reg2) (fixRI ri)
XORIS reg1 reg2 imm -> XORIS (env reg1) (env reg2) imm
EXTS fmt reg1 reg2 -> EXTS fmt (env reg1) (env reg2)
CNTLZ fmt reg1 reg2 -> CNTLZ fmt (env reg1) (env reg2)
NEG reg1 reg2 -> NEG (env reg1) (env reg2)
NOT reg1 reg2 -> NOT (env reg1) (env reg2)
SL fmt reg1 reg2 ri
......@@ -434,6 +430,7 @@ ppc_patchRegsOfInstr instr env
-> SRA fmt (env reg1) (env reg2) (fixRI ri)
RLWINM reg1 reg2 sh mb me
-> RLWINM (env reg1) (env reg2) sh mb me
CLRLI fmt reg1 reg2 n -> CLRLI fmt (env reg1) (env reg2) n
CLRRI fmt reg1 reg2 n -> CLRRI fmt (env reg1) (env reg2) n
FADD fmt r1 r2 r3 -> FADD fmt (env r1) (env r2) (env r3)
FSUB fmt r1 r2 r3 -> FSUB fmt (env r1) (env r2) (env r3)
......@@ -448,7 +445,6 @@ ppc_patchRegsOfInstr instr env
MFCR reg -> MFCR (env reg)
MFLR reg -> MFLR (env reg)
FETCHPC reg -> FETCHPC (env reg)
FETCHTOC reg lab -> FETCHTOC (env reg) lab
_ -> instr
where
fixAddr (AddrRegReg r1 r2) = AddrRegReg (env r1) (env r2)
......
......@@ -229,20 +229,20 @@ pprReg r
pprFormat :: Format -> SDoc
pprFormat x
= ptext (case x of
II8 -> sLit "b"
II16 -> sLit "h"
II32 -> sLit "w"
II64 -> sLit "d"
FF32 -> sLit "fs"
FF64 -> sLit "fd"
_ -> panic "PPC.Ppr.pprFormat: no match")
II8 -> sLit "b"
II16 -> sLit "h"
II32 -> sLit "w"
II64 -> sLit "d"
FF32 -> sLit "fs"
FF64 -> sLit "fd"
_ -> panic "PPC.Ppr.pprFormat: no match")
pprCond :: Cond -> SDoc
pprCond c
= ptext (case c of {
ALWAYS -> sLit "";
EQQ -> sLit "eq"; NE -> sLit "ne";
EQQ -> sLit "eq"; NE -> sLit "ne";
LTT -> sLit "lt"; GE -> sLit "ge";
GTT -> sLit "gt"; LE -> sLit "le";
LU -> sLit "lt"; GEU -> sLit "ge";
......@@ -493,7 +493,6 @@ pprInstr (STFAR fmt reg (AddrRegImm source off)) =
pprInstr (ADDIS (tmpReg platform) source (HA off)),
pprInstr (ST fmt reg (AddrRegImm (tmpReg platform) (LO off)))
]
pprInstr (STFAR _ _ _) =
panic "PPC.Ppr.pprInstr STFAR: no match"
pprInstr (STU fmt reg addr) = hcat [
......@@ -638,9 +637,9 @@ pprInstr (BCTRL _) = hcat [
text "bctrl"
]
pprInstr (ADD reg1 reg2 ri) = pprLogic (sLit "add") reg1 reg2 ri
pprInstr (ADDI reg1 reg2 imm) = hcat [
pprInstr (ADDIS reg1 reg2 imm) = hcat [
char '\t',
text "addi",
text "addis",
char '\t',
pprReg reg1,
text ", ",
......@@ -648,50 +647,85 @@ pprInstr (ADDI reg1 reg2 imm) = hcat [
text ", ",
pprImm imm
]
pprInstr (ADDIS reg1 reg2 imm) = hcat [
pprInstr (ADDO reg1 reg2 reg3) = pprLogic (sLit "addo") reg1 reg2 (RIReg reg3)
pprInstr (ADDC reg1 reg2 reg3) = pprLogic (sLit "addc") reg1 reg2 (RIReg reg3)
pprInstr (ADDE reg1 reg2 reg3) = pprLogic (sLit "adde") reg1 reg2 (RIReg reg3)
pprInstr (ADDZE reg1 reg2) = pprUnary (sLit "addze") reg1 reg2
pprInstr (SUBF reg1 reg2 reg3) = pprLogic (sLit "subf") reg1 reg2 (RIReg reg3)
pprInstr (SUBFO reg1 reg2 reg3) = pprLogic (sLit "subfo") reg1 reg2 (RIReg reg3)
pprInstr (SUBFC reg1 reg2 ri) = hcat [
char '\t',
text "addis",
text "subf",
case ri of
RIReg _ -> empty
RIImm _ -> char 'i',
text "c\t",
pprReg reg1,
text ", ",
pprReg reg2,
text ", ",
pprRI ri
]
pprInstr (SUBFE reg1 reg2 reg3) = pprLogic (sLit "subfe") reg1 reg2 (RIReg reg3)
pprInstr (MULL fmt reg1 reg2 ri) = pprMul fmt reg1 reg2 ri
pprInstr (MULLO fmt reg1 reg2 reg3) = hcat [
char '\t',
text "mull",
case fmt of
II32 -> char 'w'
II64 -> char 'd'
_ -> panic "PPC: illegal format",
text "o\t",
pprReg reg1,
text ", ",
pprReg reg2,
text ", ",
pprImm imm
pprReg reg3
]
pprInstr (MFOV fmt reg) = vcat [
hcat [
char '\t',
text "mfxer",
char '\t',
pprReg reg
],
hcat [
char '\t',
text "extr",
case fmt of
II32 -> char 'w'
II64 -> char 'd'
_ -> panic "PPC: illegal format",
text "i\t",
pprReg reg,
text ", ",
pprReg reg,
text ", 1, ",
case fmt of
II32 -> text "1"
II64 -> text "33"
_ -> panic "PPC: illegal format"
]
]
pprInstr (ADDC reg1 reg2 reg3) = pprLogic (sLit "addc") reg1 reg2 (RIReg reg3)
pprInstr (ADDE reg1 reg2 reg3) = pprLogic (sLit "adde") reg1 reg2 (RIReg reg3)
pprInstr (SUBF reg1 reg2 reg3) = pprLogic (sLit "subf") reg1 reg2 (RIReg reg3)
pprInstr (SUBFC reg1 reg2 reg3) = pprLogic (sLit "subfc") reg1 reg2 (RIReg reg3)
pprInstr (SUBFE reg1 reg2 reg3) = pprLogic (sLit "subfe") reg1 reg2 (RIReg reg3)
pprInstr (MULLD reg1 reg2 ri@(RIReg _)) = pprLogic (sLit "mulld") reg1 reg2 ri
pprInstr (MULLW reg1 reg2 ri@(RIReg _)) = pprLogic (sLit "mullw") reg1 reg2 ri
pprInstr (MULLD reg1 reg2 ri@(RIImm _)) = pprLogic (sLit "mull") 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 (DIVD reg1 reg2 reg3) = pprLogic (sLit "divd") reg1 reg2 (RIReg reg3)
pprInstr (DIVWU reg1 reg2 reg3) = pprLogic (sLit "divwu") reg1 reg2 (RIReg reg3)
pprInstr (DIVDU reg1 reg2 reg3) = pprLogic (sLit "divdu") reg1 reg2 (RIReg reg3)
pprInstr (MULLW_MayOflo reg1 reg2 reg3) = vcat [
hcat [ text "\tmullwo\t", pprReg reg1, ptext (sLit ", "),
pprReg reg2, text ", ",
pprReg reg3 ],
hcat [ text "\tmfxer\t", pprReg reg1 ],
hcat [ text "\trlwinm\t", pprReg reg1, ptext (sLit ", "),
pprReg reg1, text ", ",
text "2, 31, 31" ]
]
pprInstr (MULLD_MayOflo reg1 reg2 reg3) = vcat [
hcat [ text "\tmulldo\t", pprReg reg1, ptext (sLit ", "),
pprReg reg2, text ", ",
pprReg reg3 ],
hcat [ text "\tmfxer\t", pprReg reg1 ],
hcat [ text "\trlwinm\t", pprReg reg1, ptext (sLit ", "),
pprReg reg1, text ", ",
text "2, 31, 31" ]
pprInstr (MULHU fmt reg1 reg2 reg3) = hcat [
char '\t',
text "mulh",
case fmt of
II32 -> char 'w'
II64 -> char 'd'
_ -> panic "PPC: illegal format",
text "u\t",
pprReg reg1,
text ", ",
pprReg reg2,
text ", ",
pprReg reg3
]
pprInstr (DIV fmt sgn reg1 reg2 reg3) = pprDiv fmt sgn reg1 reg2 reg3
-- for some reason, "andi" doesn't exist.
-- we'll use "andi." instead.
pprInstr (AND reg1 reg2 (RIImm imm)) = hcat [
......@@ -705,6 +739,7 @@ pprInstr (AND reg1 reg2 (RIImm imm)) = hcat [
pprImm imm
]
pprInstr (AND reg1 reg2 ri) = pprLogic (sLit "and") reg1 reg2 ri
pprInstr (ANDC reg1 reg2 reg3) = pprLogic (sLit "andc") reg1 reg2 (RIReg reg3)
pprInstr (OR reg1 reg2 ri) = pprLogic (sLit "or") reg1 reg2 ri
pprInstr (XOR reg1 reg2 ri) = pprLogic (sLit "xor") reg1 reg2 ri
......@@ -740,6 +775,18 @@ pprInstr (EXTS fmt reg1 reg2) = hcat [
text ", ",
pprReg reg2
]
pprInstr (CNTLZ fmt reg1 reg2) = hcat [
char '\t',
text "cntlz",
case fmt of
II32 -> char 'w'
II64 -> char 'd'
_ -> panic "PPC: illegal format",
char '\t',
pprReg reg1,
text ", ",
pprReg reg2
]
pprInstr (NEG reg1 reg2) = pprUnary (sLit "neg") reg1 reg2
pprInstr (NOT reg1 reg2) = pprUnary (sLit "not") reg1 reg2
......@@ -798,6 +845,16 @@ pprInstr (RLWINM reg1 reg2 sh mb me) = hcat [
int me
]
pprInstr (CLRLI fmt reg1 reg2 n) = hcat [
text "\tclrl",
pprFormat fmt,
text "i ",
pprReg reg1,
text ", ",
pprReg reg2,
text ", ",
int n
]
pprInstr (CLRRI fmt reg1 reg2 n) = hcat [
text "\tclrr",
pprFormat fmt,
......@@ -863,18 +920,6 @@ pprInstr (FETCHPC reg) = vcat [
hcat [ text "1:\tmflr\t", pprReg reg ]
]
pprInstr (FETCHTOC reg lab) = vcat [
hcat [ text "0:\taddis\t", pprReg reg,
text ",12,.TOC.-0b@ha" ],
hcat [ text "\taddi\t", pprReg reg,
char ',', pprReg reg,
text ",.TOC.-0b@l" ],
hcat [ text "\t.localentry\t",
ppr lab,
text ",.-",
ppr lab]
]
pprInstr LWSYNC = text "\tlwsync"
pprInstr NOP = text "\tnop"
......@@ -914,6 +959,43 @@ pprLogic op reg1 reg2 ri = hcat [
]
pprMul :: Format -> Reg -> Reg -> RI -> SDoc
pprMul fmt reg1 reg2 ri = hcat [
char '\t',
text "mull",
case ri of
RIReg _ -> case fmt of
II32 -> char 'w'
II64 -> char 'd'
_ -> panic "PPC: illegal format"
RIImm _ -> char 'i',
char '\t',
pprReg reg1,
text ", ",
pprReg reg2,
text ", ",
pprRI ri
]
pprDiv :: Format -> Bool -> Reg -> Reg -> Reg -> SDoc
pprDiv fmt sgn reg1 reg2 reg3 = hcat [
char '\t',
text "div",
case fmt of
II32 -> char 'w'
II64 -> char 'd'
_ -> panic "PPC: illegal format",
if sgn then empty else char 'u',
char '\t',
pprReg reg1,
text ", ",
pprReg reg2,
text ", ",
pprReg reg3
]
pprUnary :: LitString -> Reg -> Reg -> SDoc
pprUnary op reg1 reg2 = hcat [
char '\t',
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment