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

Implement PowerPC 64-bit native code backend for Linux

Extend the PowerPC 32-bit native code generator for "64-bit
PowerPC ELF Application Binary Interface Supplement 1.9" by
Ian Lance Taylor and "Power Architecture 64-Bit ELF V2 ABI Specification --
OpenPOWER ABI for Linux Supplement" by IBM.
The latter ABI is mainly used on POWER7/7+ and POWER8
Linux systems running in little-endian mode. The code generator
supports both static and dynamic linking. PowerPC 64-bit
code for ELF ABI 1.9 and 2 is mostly position independent
anyway, and thus so is all the code emitted by the code
generator. In other words, -fPIC does not make a difference.

rts/stg/SMP.h support is implemented.

Following the spirit of the introductory comment in
PPC/CodeGen.hs, the rest of the code is a straightforward
extension of the 32-bit implementation.

Limitations:
* Code is generated only in the medium code model, which
  is also gcc's default
* Local symbols are not accessed directly, which seems to
  also be the case for 32-bit
* LLVM does not work, but this does not work on 32-bit either
* Must use the system runtime linker in GHCi, because the
  GHC linker for "static" object files (rts/Linker.c) for
  PPC 64-bit is not implemented. The system runtime
  (dynamic) linker works.
* The handling of the system stack (register 1) is not ELF-
  compliant so stack traces break. Instead of allocating a new
  stack frame, spill code should use the "official" spill area
  in the current stack frame and deallocation code should restore
  the back chain
* DWARF support is missing

Fixes #9863

Test Plan: validate (on powerpc, too)

Reviewers: simonmar, trofi, erikd, austin

Reviewed By: trofi

Subscribers: bgamari, arnons1, kgardas, thomie

Differential Revision: https://phabricator.haskell.org/D629

GHC Trac Issues: #9863
parent bdf7f133
......@@ -188,7 +188,10 @@ AC_DEFUN([FPTOOLS_SET_HASKELL_PLATFORM_VARS],
test -z "[$]2" || eval "[$]2=ArchPPC"
;;
powerpc64)
test -z "[$]2" || eval "[$]2=ArchPPC_64"
test -z "[$]2" || eval "[$]2=\"ArchPPC_64 {ppc_64ABI = ELF_V1}\""
;;
powerpc64le)
test -z "[$]2" || eval "[$]2=\"ArchPPC_64 {ppc_64ABI = ELF_V2}\""
;;
sparc)
test -z "[$]2" || eval "[$]2=ArchSPARC"
......@@ -209,7 +212,7 @@ AC_DEFUN([FPTOOLS_SET_HASKELL_PLATFORM_VARS],
mipsel)
test -z "[$]2" || eval "[$]2=ArchMipsel"
;;
hppa|hppa1_1|ia64|m68k|powerpc64le|rs6000|s390|s390x|sparc64|vax)
hppa|hppa1_1|ia64|m68k|rs6000|s390|s390x|sparc64|vax)
test -z "[$]2" || eval "[$]2=ArchUnknown"
;;
*)
......
......@@ -1177,16 +1177,24 @@ pprDynamicLinkerAsmLabel platform dllInfo lbl
else if osElfTarget (platformOS platform)
then if platformArch platform == ArchPPC
then case dllInfo of
CodeStub -> -- See Note [.LCTOC1 in PPC PIC code]
ppr lbl <> text "+32768@plt"
SymbolPtr -> text ".LC_" <> ppr lbl
_ -> panic "pprDynamicLinkerAsmLabel"
CodeStub -> -- See Note [.LCTOC1 in PPC PIC code]
ppr lbl <> text "+32768@plt"
SymbolPtr -> text ".LC_" <> ppr lbl
_ -> panic "pprDynamicLinkerAsmLabel"
else if platformArch platform == ArchX86_64
then case dllInfo of
CodeStub -> ppr lbl <> text "@plt"
GotSymbolPtr -> ppr lbl <> text "@gotpcrel"
GotSymbolOffset -> ppr lbl
SymbolPtr -> text ".LC_" <> ppr lbl
else if platformArch platform == ArchPPC_64 ELF_V1
|| platformArch platform == ArchPPC_64 ELF_V2
then case dllInfo of
GotSymbolPtr -> text ".LC_" <> ppr lbl
<> text "@toc"
GotSymbolOffset -> ppr lbl
SymbolPtr -> text ".LC_" <> ppr lbl
_ -> panic "pprDynamicLinkerAsmLabel"
else case dllInfo of
CodeStub -> ppr lbl <> text "@plt"
SymbolPtr -> text ".LC_" <> ppr lbl
......
......@@ -31,7 +31,7 @@ callerSaves platform
ArchARM {} -> ARM.callerSaves
ArchARM64 -> ARM64.callerSaves
arch
| arch `elem` [ArchPPC, ArchPPC_64] ->
| arch `elem` [ArchPPC, ArchPPC_64 ELF_V1, ArchPPC_64 ELF_V2] ->
case platformOS platform of
OSDarwin -> PPC_Darwin.callerSaves
_ -> PPC.callerSaves
......@@ -54,7 +54,7 @@ activeStgRegs platform
ArchARM {} -> ARM.activeStgRegs
ArchARM64 -> ARM64.activeStgRegs
arch
| arch `elem` [ArchPPC, ArchPPC_64] ->
| arch `elem` [ArchPPC, ArchPPC_64 ELF_V1, ArchPPC_64 ELF_V2] ->
case platformOS platform of
OSDarwin -> PPC_Darwin.activeStgRegs
_ -> PPC.activeStgRegs
......@@ -72,7 +72,7 @@ haveRegBase platform
ArchARM {} -> ARM.haveRegBase
ArchARM64 -> ARM64.haveRegBase
arch
| arch `elem` [ArchPPC, ArchPPC_64] ->
| arch `elem` [ArchPPC, ArchPPC_64 ELF_V1, ArchPPC_64 ELF_V2] ->
case platformOS platform of
OSDarwin -> PPC_Darwin.haveRegBase
_ -> PPC.haveRegBase
......@@ -90,7 +90,7 @@ globalRegMaybe platform
ArchARM {} -> ARM.globalRegMaybe
ArchARM64 -> ARM64.globalRegMaybe
arch
| arch `elem` [ArchPPC, ArchPPC_64] ->
| arch `elem` [ArchPPC, ArchPPC_64 ELF_V1, ArchPPC_64 ELF_V2] ->
case platformOS platform of
OSDarwin -> PPC_Darwin.globalRegMaybe
_ -> PPC.globalRegMaybe
......@@ -108,7 +108,7 @@ freeReg platform
ArchARM {} -> ARM.freeReg
ArchARM64 -> ARM64.freeReg
arch
| arch `elem` [ArchPPC, ArchPPC_64] ->
| arch `elem` [ArchPPC, ArchPPC_64 ELF_V1, ArchPPC_64 ELF_V2] ->
case platformOS platform of
OSDarwin -> PPC_Darwin.freeReg
_ -> PPC.freeReg
......
......@@ -166,18 +166,18 @@ nativeCodeGen dflags this_mod modLoc h us cmms
=> NcgImpl statics instr jumpDest -> IO UniqSupply
nCG' ncgImpl = nativeCodeGen' dflags this_mod modLoc ncgImpl h us cmms
in case platformArch platform of
ArchX86 -> nCG' (x86NcgImpl dflags)
ArchX86_64 -> nCG' (x86_64NcgImpl dflags)
ArchPPC -> nCG' (ppcNcgImpl dflags)
ArchSPARC -> nCG' (sparcNcgImpl dflags)
ArchARM {} -> panic "nativeCodeGen: No NCG for ARM"
ArchARM64 -> panic "nativeCodeGen: No NCG for ARM64"
ArchPPC_64 -> panic "nativeCodeGen: No NCG for PPC 64"
ArchAlpha -> panic "nativeCodeGen: No NCG for Alpha"
ArchMipseb -> panic "nativeCodeGen: No NCG for mipseb"
ArchMipsel -> panic "nativeCodeGen: No NCG for mipsel"
ArchUnknown -> panic "nativeCodeGen: No NCG for unknown arch"
ArchJavaScript -> panic "nativeCodeGen: No NCG for JavaScript"
ArchX86 -> nCG' (x86NcgImpl dflags)
ArchX86_64 -> nCG' (x86_64NcgImpl dflags)
ArchPPC -> nCG' (ppcNcgImpl dflags)
ArchSPARC -> nCG' (sparcNcgImpl dflags)
ArchARM {} -> panic "nativeCodeGen: No NCG for ARM"
ArchARM64 -> panic "nativeCodeGen: No NCG for ARM64"
ArchPPC_64 _ -> nCG' (ppcNcgImpl dflags)
ArchAlpha -> panic "nativeCodeGen: No NCG for Alpha"
ArchMipseb -> panic "nativeCodeGen: No NCG for mipseb"
ArchMipsel -> panic "nativeCodeGen: No NCG for mipsel"
ArchUnknown -> panic "nativeCodeGen: No NCG for unknown arch"
ArchJavaScript-> panic "nativeCodeGen: No NCG for JavaScript"
x86NcgImpl :: DynFlags -> NcgImpl (Alignment, CmmStatics) X86.Instr.Instr X86.Instr.JumpDest
x86NcgImpl dflags
......
......@@ -158,7 +158,14 @@ cmmMakePicReference dflags lbl
-- everything gets relocated at runtime
| OSMinGW32 <- platformOS $ targetPlatform dflags
= CmmLit $ CmmLabel lbl
-- both ABI versions default to medium code model
| ArchPPC_64 _ <- platformArch $ targetPlatform dflags
= CmmMachOp (MO_Add W32) -- code model medium
[ CmmReg (CmmGlobal PicBaseReg)
, CmmLit $ picRelative
(platformArch $ targetPlatform dflags)
(platformOS $ targetPlatform dflags)
lbl ]
| (gopt Opt_PIC dflags || not (gopt Opt_Static dflags)) && absoluteLabel lbl
= CmmMachOp (MO_Add (wordWidth dflags))
......@@ -293,13 +300,17 @@ howToAccessLabel dflags arch OSDarwin this_mod _ lbl
-- from position independent code. It is also required from the main program
-- when dynamic libraries containing Haskell code are used.
howToAccessLabel _ ArchPPC_64 os _ kind _
howToAccessLabel _ (ArchPPC_64 _) os _ kind _
| osElfTarget os
= if kind == DataReference
-- ELF PPC64 (powerpc64-linux), AIX, MacOS 9, BeOS/PPC
then AccessViaSymbolPtr
-- actually, .label instead of label
else AccessDirectly
= case kind of
-- ELF PPC64 (powerpc64-linux), AIX, MacOS 9, BeOS/PPC
DataReference -> AccessViaSymbolPtr
-- RTLD does not generate stubs for function descriptors
-- in tail calls. Create a symbol pointer and generate
-- the code to load the function descriptor at the call site.
JumpReference -> AccessViaSymbolPtr
-- regular calls are handled by the runtime linker
_ -> AccessDirectly
howToAccessLabel dflags _ os _ _ _
-- no PIC -> the dynamic linker does everything for us;
......@@ -430,9 +441,14 @@ needImportedSymbols dflags arch os
, arch == ArchPPC
= gopt Opt_PIC dflags || not (gopt Opt_Static dflags)
-- PowerPC 64 Linux: always
| osElfTarget os
, arch == ArchPPC_64 ELF_V1 || arch == ArchPPC_64 ELF_V2
= True
-- i386 (and others?): -dynamic but not -fPIC
| osElfTarget os
, arch /= ArchPPC_64
, arch /= ArchPPC_64 ELF_V1 && arch /= ArchPPC_64 ELF_V2
= not (gopt Opt_Static dflags) && not (gopt Opt_PIC dflags)
| otherwise
......@@ -467,16 +483,30 @@ pprGotDeclaration dflags ArchX86 OSDarwin
pprGotDeclaration _ _ OSDarwin
= empty
-- PPC 64 ELF v1needs a Table Of Contents (TOC) on Linux
pprGotDeclaration _ (ArchPPC_64 ELF_V1) OSLinux
= ptext (sLit ".section \".toc\",\"aw\"")
-- In ELF v2 we also need to tell the assembler that we want ABI
-- version 2. This would normally be done at the top of the file
-- right after a file directive, but I could not figure out how
-- to do that.
pprGotDeclaration _ (ArchPPC_64 ELF_V2) OSLinux
= vcat [ ptext (sLit ".abiversion 2"),
ptext (sLit ".section \".toc\",\"aw\"")
]
pprGotDeclaration _ (ArchPPC_64 _) _
= panic "pprGotDeclaration: ArchPPC_64 only Linux supported"
-- Emit GOT declaration
-- Output whatever needs to be output once per .s file.
pprGotDeclaration dflags arch os
| osElfTarget os
, arch /= ArchPPC_64
, arch /= ArchPPC_64 ELF_V1 && arch /= ArchPPC_64 ELF_V2
, not (gopt Opt_PIC dflags)
= empty
| osElfTarget os
, arch /= ArchPPC_64
, arch /= ArchPPC_64 ELF_V1 && arch /= ArchPPC_64 ELF_V2
= vcat [
-- See Note [.LCTOC1 in PPC PIC code]
ptext (sLit ".section \".got2\",\"aw\""),
......@@ -635,9 +665,16 @@ pprImportedSymbol _ (Platform { platformOS = OSDarwin }) _
-- the NCG will keep track of all DynamicLinkerLabels it uses
-- and output each of them using pprImportedSymbol.
pprImportedSymbol _ platform@(Platform { platformArch = ArchPPC_64 }) _
pprImportedSymbol _ platform@(Platform { platformArch = ArchPPC_64 _ })
importedLbl
| osElfTarget (platformOS platform)
= empty
= case dynamicLinkerLabelInfo importedLbl of
Just (SymbolPtr, lbl)
-> vcat [
ptext (sLit ".section \".toc\", \"aw\""),
ptext (sLit ".LC_") <> pprCLabel platform lbl <> char ':',
ptext (sLit "\t.quad") <+> pprCLabel platform lbl ]
_ -> empty
pprImportedSymbol dflags platform importedLbl
| osElfTarget (platformOS platform)
......@@ -735,6 +772,28 @@ initializePicBase_ppc ArchPPC OSDarwin picReg
where BasicBlock bID insns = entry
b' = BasicBlock bID (PPC.FETCHPC picReg : insns)
-------------------------------------------------------------------------
-- Load TOC into register 2
-- PowerPC 64-bit ELF ABI 2.0 requires the address of the callee
-- in register 12.
-- We pass the label to FETCHTOC and create a .localentry too.
-- TODO: Explain this better and refer to ABI spec!
{-
We would like to do approximately this, but spill slot allocation
might be added before the first BasicBlock. That violates the ABI.
For now we will emit the prologue code in the pretty printer,
which is also what we do for ELF v1.
initializePicBase_ppc (ArchPPC_64 ELF_V2) OSLinux picReg
(CmmProc info lab live (ListGraph (entry:blocks)) : statics)
= do
bID <-getUniqueM
return (CmmProc info lab live (ListGraph (b':entry:blocks))
: statics)
where BasicBlock entryID _ = entry
b' = BasicBlock bID [PPC.FETCHTOC picReg lab,
PPC.BCC PPC.ALWAYS entryID]
-}
initializePicBase_ppc _ _ _ _
= panic "initializePicBase_ppc: not needed"
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -37,7 +37,7 @@ module PPC.Regs (
fits16Bits,
makeImmediate,
fReg,
sp, r3, r4, r27, r28, r30,
sp, toc, r3, r4, r11, r12, r27, r28, r30,
f1, f20, f21,
allocatableRegs
......@@ -64,8 +64,8 @@ import FastBool
import FastTypes
import Platform
import Data.Word ( Word8, Word16, Word32 )
import Data.Int ( Int8, Int16, Int32 )
import Data.Word ( Word8, Word16, Word32, Word64 )
import Data.Int ( Int8, Int16, Int32, Int64 )
-- squeese functions for the graph allocator -----------------------------------
......@@ -147,6 +147,8 @@ data Imm
| LO Imm
| HI Imm
| HA Imm {- high halfword adjusted -}
| HIGHERA Imm
| HIGHESTA Imm
strImmLit :: String -> Imm
......@@ -269,9 +271,11 @@ fits16Bits x = x >= -32768 && x < 32768
makeImmediate :: Integral a => Width -> Bool -> a -> Maybe Imm
makeImmediate rep signed x = fmap ImmInt (toI16 rep signed)
where
narrow W64 False = fromIntegral (fromIntegral x :: Word64)
narrow W32 False = fromIntegral (fromIntegral x :: Word32)
narrow W16 False = fromIntegral (fromIntegral x :: Word16)
narrow W8 False = fromIntegral (fromIntegral x :: Word8)
narrow W64 True = fromIntegral (fromIntegral x :: Int64)
narrow W32 True = fromIntegral (fromIntegral x :: Int32)
narrow W16 True = fromIntegral (fromIntegral x :: Int16)
narrow W8 True = fromIntegral (fromIntegral x :: Int8)
......@@ -285,6 +289,12 @@ makeImmediate rep signed x = fmap ImmInt (toI16 rep signed)
toI16 W32 False
| narrowed >= 0 && narrowed < 65536 = Just narrowed
| otherwise = Nothing
toI16 W64 True
| narrowed >= -32768 && narrowed < 32768 = Just narrowed
| otherwise = Nothing
toI16 W64 False
| narrowed >= 0 && narrowed < 65536 = Just narrowed
| otherwise = Nothing
toI16 _ _ = Just narrowed
......@@ -296,10 +306,13 @@ point registers.
fReg :: Int -> RegNo
fReg x = (32 + x)
sp, r3, r4, r27, r28, r30, f1, f20, f21 :: Reg
sp, toc, r3, r4, r11, r12, r27, r28, r30, f1, f20, f21 :: Reg
sp = regSingle 1
toc = regSingle 2
r3 = regSingle 3
r4 = regSingle 4
r11 = regSingle 11
r12 = regSingle 12
r27 = regSingle 27
r28 = regSingle 28
r30 = regSingle 30
......
......@@ -111,7 +111,7 @@ trivColorable platform virtualRegSqueeze realRegSqueeze RcInteger conflicts excl
ArchX86_64 -> 5
ArchPPC -> 16
ArchSPARC -> 14
ArchPPC_64 -> panic "trivColorable ArchPPC_64"
ArchPPC_64 _ -> panic "trivColorable ArchPPC_64"
ArchARM _ _ _ -> panic "trivColorable ArchARM"
ArchARM64 -> panic "trivColorable ArchARM64"
ArchAlpha -> panic "trivColorable ArchAlpha"
......@@ -136,7 +136,7 @@ trivColorable platform virtualRegSqueeze realRegSqueeze RcFloat conflicts exclus
ArchX86_64 -> 0
ArchPPC -> 0
ArchSPARC -> 22
ArchPPC_64 -> panic "trivColorable ArchPPC_64"
ArchPPC_64 _ -> panic "trivColorable ArchPPC_64"
ArchARM _ _ _ -> panic "trivColorable ArchARM"
ArchARM64 -> panic "trivColorable ArchARM64"
ArchAlpha -> panic "trivColorable ArchAlpha"
......@@ -161,7 +161,7 @@ trivColorable platform virtualRegSqueeze realRegSqueeze RcDouble conflicts exclu
ArchX86_64 -> 0
ArchPPC -> 26
ArchSPARC -> 11
ArchPPC_64 -> panic "trivColorable ArchPPC_64"
ArchPPC_64 _ -> panic "trivColorable ArchPPC_64"
ArchARM _ _ _ -> panic "trivColorable ArchARM"
ArchARM64 -> panic "trivColorable ArchARM64"
ArchAlpha -> panic "trivColorable ArchAlpha"
......@@ -186,7 +186,7 @@ trivColorable platform virtualRegSqueeze realRegSqueeze RcDoubleSSE conflicts ex
ArchX86_64 -> 10
ArchPPC -> 0
ArchSPARC -> 0
ArchPPC_64 -> panic "trivColorable ArchPPC_64"
ArchPPC_64 _ -> panic "trivColorable ArchPPC_64"
ArchARM _ _ _ -> panic "trivColorable ArchARM"
ArchARM64 -> panic "trivColorable ArchARM64"
ArchAlpha -> panic "trivColorable ArchAlpha"
......
......@@ -76,7 +76,7 @@ maxSpillSlots dflags
ArchSPARC -> SPARC.Instr.maxSpillSlots dflags
ArchARM _ _ _ -> panic "maxSpillSlots ArchARM"
ArchARM64 -> panic "maxSpillSlots ArchARM64"
ArchPPC_64 -> panic "maxSpillSlots ArchPPC_64"
ArchPPC_64 _ -> PPC.Instr.maxSpillSlots dflags
ArchAlpha -> panic "maxSpillSlots ArchAlpha"
ArchMipseb -> panic "maxSpillSlots ArchMipseb"
ArchMipsel -> panic "maxSpillSlots ArchMipsel"
......
......@@ -211,7 +211,7 @@ linearRegAlloc dflags entry_ids block_live sccs
ArchPPC -> go $ (frInitFreeRegs platform :: PPC.FreeRegs)
ArchARM _ _ _ -> panic "linearRegAlloc ArchARM"
ArchARM64 -> panic "linearRegAlloc ArchARM64"
ArchPPC_64 -> panic "linearRegAlloc ArchPPC_64"
ArchPPC_64 _ -> go $ (frInitFreeRegs platform :: PPC.FreeRegs)
ArchAlpha -> panic "linearRegAlloc ArchAlpha"
ArchMipseb -> panic "linearRegAlloc ArchMipseb"
ArchMipsel -> panic "linearRegAlloc ArchMipsel"
......
......@@ -44,7 +44,7 @@ targetVirtualRegSqueeze platform
ArchX86_64 -> X86.virtualRegSqueeze
ArchPPC -> PPC.virtualRegSqueeze
ArchSPARC -> SPARC.virtualRegSqueeze
ArchPPC_64 -> panic "targetVirtualRegSqueeze ArchPPC_64"
ArchPPC_64 _ -> PPC.virtualRegSqueeze
ArchARM _ _ _ -> panic "targetVirtualRegSqueeze ArchARM"
ArchARM64 -> panic "targetVirtualRegSqueeze ArchARM64"
ArchAlpha -> panic "targetVirtualRegSqueeze ArchAlpha"
......@@ -61,7 +61,7 @@ targetRealRegSqueeze platform
ArchX86_64 -> X86.realRegSqueeze
ArchPPC -> PPC.realRegSqueeze
ArchSPARC -> SPARC.realRegSqueeze
ArchPPC_64 -> panic "targetRealRegSqueeze ArchPPC_64"
ArchPPC_64 _ -> PPC.realRegSqueeze
ArchARM _ _ _ -> panic "targetRealRegSqueeze ArchARM"
ArchARM64 -> panic "targetRealRegSqueeze ArchARM64"
ArchAlpha -> panic "targetRealRegSqueeze ArchAlpha"
......@@ -77,7 +77,7 @@ targetClassOfRealReg platform
ArchX86_64 -> X86.classOfRealReg platform
ArchPPC -> PPC.classOfRealReg
ArchSPARC -> SPARC.classOfRealReg
ArchPPC_64 -> panic "targetClassOfRealReg ArchPPC_64"
ArchPPC_64 _ -> PPC.classOfRealReg
ArchARM _ _ _ -> panic "targetClassOfRealReg ArchARM"
ArchARM64 -> panic "targetClassOfRealReg ArchARM64"
ArchAlpha -> panic "targetClassOfRealReg ArchAlpha"
......@@ -93,7 +93,7 @@ targetMkVirtualReg platform
ArchX86_64 -> X86.mkVirtualReg
ArchPPC -> PPC.mkVirtualReg
ArchSPARC -> SPARC.mkVirtualReg
ArchPPC_64 -> panic "targetMkVirtualReg ArchPPC_64"
ArchPPC_64 _ -> PPC.mkVirtualReg
ArchARM _ _ _ -> panic "targetMkVirtualReg ArchARM"
ArchARM64 -> panic "targetMkVirtualReg ArchARM64"
ArchAlpha -> panic "targetMkVirtualReg ArchAlpha"
......@@ -109,7 +109,7 @@ targetRegDotColor platform
ArchX86_64 -> X86.regDotColor platform
ArchPPC -> PPC.regDotColor
ArchSPARC -> SPARC.regDotColor
ArchPPC_64 -> panic "targetRegDotColor ArchPPC_64"
ArchPPC_64 _ -> PPC.regDotColor
ArchARM _ _ _ -> panic "targetRegDotColor ArchARM"
ArchARM64 -> panic "targetRegDotColor ArchARM64"
ArchAlpha -> panic "targetRegDotColor ArchAlpha"
......
......@@ -8,6 +8,7 @@ module Platform (
ArmISA(..),
ArmISAExt(..),
ArmABI(..),
PPC_64ABI(..),
target32Bit,
isARM,
......@@ -47,6 +48,8 @@ data Arch
| ArchX86_64
| ArchPPC
| ArchPPC_64
{ ppc_64ABI :: PPC_64ABI
}
| ArchSPARC
| ArchARM
{ armISA :: ArmISA
......@@ -107,10 +110,18 @@ data ArmABI
| HARD
deriving (Read, Show, Eq)
-- | PowerPC 64-bit ABI
--
data PPC_64ABI
= ELF_V1
| ELF_V2
deriving (Read, Show, Eq)
-- | This predicate tells us whether the platform is 32-bit.
target32Bit :: Platform -> Bool
target32Bit p = platformWordSize p == 4
-- | This predicates tells us whether the OS supports ELF-like shared libraries.
-- | This predicate tells us whether the OS supports ELF-like shared libraries.
osElfTarget :: OS -> Bool
osElfTarget OSLinux = True
osElfTarget OSFreeBSD = True
......
......@@ -241,7 +241,7 @@ AC_SUBST(SOLARIS_BROKEN_SHLD)
dnl ** Do an unregisterised build?
dnl --------------------------------------------------------------
case "$HostArch" in
i386|x86_64|powerpc|arm)
i386|x86_64|powerpc|powerpc64|powerpc64le|arm)
UnregisterisedDefault=NO
;;
*)
......
......@@ -881,6 +881,9 @@ freeReg 1 = fastBool False -- The Stack Pointer
# if !MACHREGS_darwin
-- most non-darwin powerpc OSes use r2 as a TOC pointer or something like that
freeReg 2 = fastBool False
-- TODO: make this conditonal for ppc64 ELF
freeReg 13 = fastBool False -- reserved for system thread ID
-- TODO: do not reserve r30 in ppc64 ELF
-- at least linux in -fPIC relies on r30 in PLT stubs
freeReg 30 = fastBool False
# endif
......
......@@ -35,7 +35,8 @@
#define MACHREGS_i386 i386_TARGET_ARCH
#define MACHREGS_x86_64 x86_64_TARGET_ARCH
#define MACHREGS_powerpc (powerpc_TARGET_ARCH || powerpc64_TARGET_ARCH || rs6000_TARGET_ARCH)
#define MACHREGS_powerpc (powerpc_TARGET_ARCH || powerpc64_TARGET_ARCH \
|| powerpc64le_TARGET_ARCH || rs6000_TARGET_ARCH)
#define MACHREGS_sparc sparc_TARGET_ARCH
#define MACHREGS_arm arm_TARGET_ARCH
#define MACHREGS_aarch64 aarch64_TARGET_ARCH
......
......@@ -41,7 +41,8 @@
#define MACHREGS_i386 i386_HOST_ARCH
#define MACHREGS_x86_64 x86_64_HOST_ARCH
#define MACHREGS_powerpc (powerpc_HOST_ARCH || powerpc64_HOST_ARCH || rs6000_HOST_ARCH)
#define MACHREGS_powerpc (powerpc_HOST_ARCH || powerpc64_HOST_ARCH \
|| powerpc64le_HOST_ARCH || rs6000_HOST_ARCH)
#define MACHREGS_sparc sparc_HOST_ARCH
#define MACHREGS_arm arm_HOST_ARCH
#define MACHREGS_aarch64 aarch64_HOST_ARCH
......
......@@ -127,6 +127,14 @@ xchg(StgPtr p, StgWord w)
:"=&r" (result)
:"r" (w), "r" (p)
);
#elif powerpc64_HOST_ARCH || powerpc64le_HOST_ARCH
__asm__ __volatile__ (
"1: ldarx %0, 0, %2\n"
" stdcx. %1, 0, %2\n"
" bne- 1b"
:"=&r" (result)
:"r" (w), "r" (p)
);
#elif sparc_HOST_ARCH
result = w;
__asm__ __volatile__ (
......@@ -208,6 +216,20 @@ cas(StgVolatilePtr p, StgWord o, StgWord n)
:"cc", "memory"
);
return result;
#elif powerpc64_HOST_ARCH || powerpc64le_HOST_ARCH
StgWord result;
__asm__ __volatile__ (
"1: ldarx %0, 0, %3\n"
" cmpd %0, %1\n"
" bne 2f\n"
" stdcx. %2, 0, %3\n"
" bne- 1b\n"
"2:"
:"=&r" (result)
:"r" (o), "r" (n), "r" (p)
:"cc", "memory"
);
return result;
#elif sparc_HOST_ARCH
__asm__ __volatile__ (
"cas [%1], %2, %0"
......@@ -345,7 +367,7 @@ write_barrier(void) {
return;
#elif i386_HOST_ARCH || x86_64_HOST_ARCH
__asm__ __volatile__ ("" : : : "memory");
#elif powerpc_HOST_ARCH
#elif powerpc_HOST_ARCH || powerpc64_HOST_ARCH || powerpc64le_HOST_ARCH
__asm__ __volatile__ ("lwsync" : : : "memory");
#elif sparc_HOST_ARCH
/* Sparc in TSO mode does not require store/store barriers. */
......@@ -367,7 +389,7 @@ store_load_barrier(void) {
__asm__ __volatile__ ("lock; addl $0,0(%%esp)" : : : "memory");
#elif x86_64_HOST_ARCH
__asm__ __volatile__ ("lock; addq $0,0(%%rsp)" : : : "memory");
#elif powerpc_HOST_ARCH
#elif powerpc_HOST_ARCH || powerpc64_HOST_ARCH || powerpc64le_HOST_ARCH
__asm__ __volatile__ ("sync" : : : "memory");
#elif sparc_HOST_ARCH
__asm__ __volatile__ ("membar #StoreLoad" : : : "memory");
......@@ -395,7 +417,7 @@ load_load_barrier(void) {
__asm__ __volatile__ ("" : : : "memory");
#elif x86_64_HOST_ARCH
__asm__ __volatile__ ("" : : : "memory");
#elif powerpc_HOST_ARCH
#elif powerpc_HOST_ARCH || powerpc64_HOST_ARCH || powerpc64le_HOST_ARCH
__asm__ __volatile__ ("lwsync" : : : "memory");
#elif sparc_HOST_ARCH
/* Sparc in TSO mode does not require load/load barriers. */
......
......@@ -145,9 +145,9 @@ GhcUnregisterised=@Unregisterised@
# (as well as a C backend)
#
# Target platforms supported:
# i386, powerpc
# i386, powerpc, powerpc64, sparc
# IOS and AIX are not supported
ArchSupportsNCG=$(strip $(patsubst $(TargetArch_CPP), YES, $(findstring $(TargetArch_CPP), i386 x86_64 powerpc sparc)))
ArchSupportsNCG=$(strip $(patsubst $(TargetArch_CPP), YES, $(findstring $(TargetArch_CPP), i386 x86_64 powerpc powerpc64 powerpc64le sparc)))
OsSupportsNCG=$(strip $(patsubst $(TargetOS_CPP), YES, $(patsubst ios,,$(patsubst aix,,$(TargetOS_CPP)))))
GhcWithNativeCodeGen := $(strip\
......@@ -158,7 +158,7 @@ HaveLibDL = @HaveLibDL@
# ArchSupportsSMP should be set iff there is support for that arch in
# includes/stg/SMP.h
ArchSupportsSMP=$(strip $(patsubst $(TargetArch_CPP), YES, $(findstring $(TargetArch_CPP), i386 x86_64 sparc powerpc arm aarch64)))
ArchSupportsSMP=$(strip $(patsubst $(TargetArch_CPP), YES, $(findstring $(TargetArch_CPP), i386 x86_64 sparc powerpc powerpc64 powerpc64le arm aarch64)))
GhcWithSMP := $(strip $(if $(filter YESNO, $(ArchSupportsSMP)$(GhcUnregisterised)),YES,NO))
......@@ -166,7 +166,7 @@ GhcWithSMP := $(strip $(if $(filter YESNO, $(ArchSupportsSMP)$(GhcUnregisterised
# has support for this OS/ARCH combination.
OsSupportsGHCi=$(strip $(patsubst $(TargetOS_CPP), YES, $(findstring $(TargetOS_CPP), mingw32 cygwin32 linux solaris2 freebsd dragonfly netbsd openbsd darwin kfreebsdgnu)))
ArchSupportsGHCi=$(strip $(patsubst $(TargetArch_CPP), YES, $(findstring $(TargetArch_CPP), i386 x86_64 powerpc sparc sparc64 arm aarch64)))
ArchSupportsGHCi=$(strip $(patsubst $(TargetArch_CPP), YES, $(findstring $(TargetArch_CPP), i386 x86_64 powerpc powerpc64 powerpc64le sparc sparc64 arm aarch64)))
ifeq "$(OsSupportsGHCi)$(ArchSupportsGHCi)" "YESYES"
GhcWithInterpreter=YES
......@@ -179,7 +179,7 @@ endif
# (see TABLES_NEXT_TO_CODE in the RTS). Whether we actually compile for
# TABLES_NEXT_TO_CODE depends on whether we're building unregisterised
# code or not, which may be decided by options to the compiler later.
ifneq "$(findstring $(TargetArch_CPP)X, ia64X powerpc64X)" ""
ifneq "$(findstring $(TargetArch_CPP)X, ia64X powerpc64X powerpc64leX)" ""
GhcEnableTablesNextToCode=NO
else
GhcEnableTablesNextToCode=YES
......
......@@ -662,11 +662,19 @@ StgRunIsImplementedInAssembler(void)
}
#else // linux_HOST_OS
#error Only linux support for power64 right now.
#error Only Linux support for power64 right now.
#endif
#endif
#ifdef powerpc64le_HOST_ARCH
/* -----------------------------------------------------------------------------
PowerPC 64 little endian architecture
Really everything is in assembler, so we don't have to deal with GCC...
-------------------------------------------------------------------------- */
#endif
/* -----------------------------------------------------------------------------
ARM architecture
-------------------------------------------------------------------------- */
......
#include "ghcconfig.h"
#include "rts/Constants.h"
#ifdef powerpc64le_HOST_ARCH
#ifdef linux_HOST_OS
#define STACK_FRAME_SIZE RESERVED_C_STACK_BYTES+304
.file "StgCRun.c"
.abiversion 2
.section ".toc","aw"
.section ".text"
.align 2
.globl StgRun
.hidden StgRun
.type StgRun,@function
StgRun:
.localentry StgRun,.-StgRun
mflr 0
mr 5, 1
std 0, 16(1)
stdu 1, -(STACK_FRAME_SIZE)(1)
std 2, -296(5)
std 14, -288(5)
std 15, -280(5)
std 16, -272(5)
std 17, -264(5)
std 18, -256(5)
std 19, -248(5)
std 20, -240(5)
std 21, -232(5)
std 22, -224(5)
std 23, -216(5)
std 24, -208(5)
std 25, -200(5)
std 26, -192(5)
std 27, -184(5)
std 28, -176(5)
std 29, -168(5)
std 30, -160(5)
std 31, -152(5)
stfd 14, -144(5)
stfd 15, -136(5)
stfd 16, -128(5)
stfd 17, -120(5)
stfd 18, -112(5)
stfd 19, -104(5)
stfd 20, -96(5)
stfd 21, -88(5)
stfd 22, -80(5)
stfd 23, -72(5)
stfd 24, -64(5)
stfd 25, -56(5)
stfd 26, -48(5)
stfd 27, -40(5)
stfd 28, -32(5)
stfd 29, -24(5)
stfd 30, -16(5)
stfd 31, -8(5)
mr 27, 4
mtctr 3
mr 12, 3
bctr
.globl StgReturn
.type StgReturn,@function
StgReturn:
.localentry StgReturn,.-StgReturn
mr 3,14
la 5, STACK_FRAME_SIZE(1)
ld 2, -296(5)
ld 14, -288(5)
ld 15, -280(5)
ld 16, -272(5)
ld 17, -264(5)
ld 18, -256(5)
ld 19, -248(5)
ld 20, -240(5)
ld 21, -232(5)
ld 22, -224(5)
ld 23, -216(5)
ld 24, -208(5)
ld 25, -200(5)
ld 26, -192(5)
ld 27, -184(5)
ld 28, -176(5)
ld 29, -168(5)
ld 30, -160(5)
ld 31, -152(5)
lfd 14, -144(5)
lfd 15, -136(5)
lfd 16, -128(5)
lfd 17, -120(5)
lfd 18, -112(5)
lfd 19, -104(5)
lfd 20, -96(5)
lfd 21, -88(5)
lfd 22, -80(5)
lfd 23, -72(5)
lfd 24, -64(5)
lfd 25, -56(5)
lfd 26, -48(5)
lfd 27, -40(5)