summaryrefslogtreecommitdiff
path: root/compiler/nativeGen/PPC/Ppr.hs
diff options
context:
space:
mode:
authorPeter Trommler <ptrommler@acm.org>2017-04-25 18:37:16 -0400
committerBen Gamari <ben@smart-cactus.org>2017-04-25 18:39:50 -0400
commit89a3241f708502e8fbcfaddbbe634790ad9cd02a (patch)
tree9264c8bb53a229ea2a6a55debd0088bb88354bd2 /compiler/nativeGen/PPC/Ppr.hs
parent9373994acaf1b73fe0e7cf8e03594c63cec8d235 (diff)
downloadhaskell-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.hs196
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',