diff options
| author | Peter Trommler <ptrommler@acm.org> | 2017-04-25 18:37:16 -0400 |
|---|---|---|
| committer | Ben Gamari <ben@smart-cactus.org> | 2017-04-25 18:39:50 -0400 |
| commit | 89a3241f708502e8fbcfaddbbe634790ad9cd02a (patch) | |
| tree | 9264c8bb53a229ea2a6a55debd0088bb88354bd2 /compiler/nativeGen/PPC/Ppr.hs | |
| parent | 9373994acaf1b73fe0e7cf8e03594c63cec8d235 (diff) | |
| download | haskell-89a3241f708502e8fbcfaddbbe634790ad9cd02a.tar.gz | |
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
Diffstat (limited to 'compiler/nativeGen/PPC/Ppr.hs')
| -rw-r--r-- | compiler/nativeGen/PPC/Ppr.hs | 196 |
1 files changed, 139 insertions, 57 deletions
diff --git a/compiler/nativeGen/PPC/Ppr.hs b/compiler/nativeGen/PPC/Ppr.hs index 0a1657ddf1..025dfaf244 100644 --- a/compiler/nativeGen/PPC/Ppr.hs +++ b/compiler/nativeGen/PPC/Ppr.hs @@ -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', |
