diff options
author | Stefan Schulze Frielinghaus <stefansf@linux.ibm.com> | 2019-10-08 12:32:15 +0200 |
---|---|---|
committer | Marge Bot <ben+marge-bot@smart-cactus.org> | 2019-10-22 02:39:03 -0400 |
commit | fd8b666acfee5524a2d7c8b845a3782f6a89bec7 (patch) | |
tree | 4ce0d732ef341bcffa721f6d25f2cf4dcd476fd8 | |
parent | aa31ceaf7568802590f73a740ffbc8b800096342 (diff) | |
download | haskell-fd8b666acfee5524a2d7c8b845a3782f6a89bec7.tar.gz |
Implement s390x LLVM backend.
This patch adds support for the s390x architecture for the LLVM code
generator. The patch includes a register mapping of STG registers onto
s390x machine registers which enables a registerised build.
27 files changed, 315 insertions, 12 deletions
diff --git a/aclocal.m4 b/aclocal.m4 index fd115e46f8..ab66dfe35d 100644 --- a/aclocal.m4 +++ b/aclocal.m4 @@ -195,6 +195,9 @@ AC_DEFUN([FPTOOLS_SET_HASKELL_PLATFORM_VARS], powerpc64le) test -z "[$]2" || eval "[$]2=\"ArchPPC_64 {ppc_64ABI = ELF_V2}\"" ;; + s390x) + test -z "[$]2" || eval "[$]2=ArchS390X" + ;; sparc) test -z "[$]2" || eval "[$]2=ArchSPARC" ;; @@ -217,7 +220,7 @@ AC_DEFUN([FPTOOLS_SET_HASKELL_PLATFORM_VARS], mipsel) test -z "[$]2" || eval "[$]2=ArchMipsel" ;; - hppa|hppa1_1|ia64|m68k|nios2|riscv32|riscv64|rs6000|s390|s390x|sh4|vax) + hppa|hppa1_1|ia64|m68k|nios2|riscv32|riscv64|rs6000|s390|sh4|vax) test -z "[$]2" || eval "[$]2=ArchUnknown" ;; *) diff --git a/compiler/GHC/Platform/Regs.hs b/compiler/GHC/Platform/Regs.hs index e7887fbe72..fe6588d067 100644 --- a/compiler/GHC/Platform/Regs.hs +++ b/compiler/GHC/Platform/Regs.hs @@ -12,6 +12,7 @@ import Reg import qualified GHC.Platform.ARM as ARM import qualified GHC.Platform.ARM64 as ARM64 import qualified GHC.Platform.PPC as PPC +import qualified GHC.Platform.S390X as S390X import qualified GHC.Platform.SPARC as SPARC import qualified GHC.Platform.X86 as X86 import qualified GHC.Platform.X86_64 as X86_64 @@ -27,6 +28,7 @@ callerSaves platform = case platformArch platform of ArchX86 -> X86.callerSaves ArchX86_64 -> X86_64.callerSaves + ArchS390X -> S390X.callerSaves ArchSPARC -> SPARC.callerSaves ArchARM {} -> ARM.callerSaves ArchARM64 -> ARM64.callerSaves @@ -48,6 +50,7 @@ activeStgRegs platform = case platformArch platform of ArchX86 -> X86.activeStgRegs ArchX86_64 -> X86_64.activeStgRegs + ArchS390X -> S390X.activeStgRegs ArchSPARC -> SPARC.activeStgRegs ArchARM {} -> ARM.activeStgRegs ArchARM64 -> ARM64.activeStgRegs @@ -64,6 +67,7 @@ haveRegBase platform = case platformArch platform of ArchX86 -> X86.haveRegBase ArchX86_64 -> X86_64.haveRegBase + ArchS390X -> S390X.haveRegBase ArchSPARC -> SPARC.haveRegBase ArchARM {} -> ARM.haveRegBase ArchARM64 -> ARM64.haveRegBase @@ -80,6 +84,7 @@ globalRegMaybe platform = case platformArch platform of ArchX86 -> X86.globalRegMaybe ArchX86_64 -> X86_64.globalRegMaybe + ArchS390X -> S390X.globalRegMaybe ArchSPARC -> SPARC.globalRegMaybe ArchARM {} -> ARM.globalRegMaybe ArchARM64 -> ARM64.globalRegMaybe @@ -96,6 +101,7 @@ freeReg platform = case platformArch platform of ArchX86 -> X86.freeReg ArchX86_64 -> X86_64.freeReg + ArchS390X -> S390X.freeReg ArchSPARC -> SPARC.freeReg ArchARM {} -> ARM.freeReg ArchARM64 -> ARM64.freeReg diff --git a/compiler/GHC/Platform/S390X.hs b/compiler/GHC/Platform/S390X.hs new file mode 100644 index 0000000000..8599bb67c0 --- /dev/null +++ b/compiler/GHC/Platform/S390X.hs @@ -0,0 +1,10 @@ +{-# LANGUAGE CPP #-} + +module GHC.Platform.S390X where + +import GhcPrelude + +#define MACHREGS_NO_REGS 0 +#define MACHREGS_s390x 1 +#include "../../../includes/CodeGen.Platform.hs" + diff --git a/compiler/ghc.cabal.in b/compiler/ghc.cabal.in index 4737d13c0b..7e9171adc9 100644 --- a/compiler/ghc.cabal.in +++ b/compiler/ghc.cabal.in @@ -285,6 +285,7 @@ Library GHC.Platform.ARM64 GHC.Platform.NoRegs GHC.Platform.PPC + GHC.Platform.S390X GHC.Platform.SPARC GHC.Platform.X86 GHC.Platform.X86_64 diff --git a/compiler/llvmGen/LlvmCodeGen/Data.hs b/compiler/llvmGen/LlvmCodeGen/Data.hs index 70a04e6bc9..4c07f8ee8f 100644 --- a/compiler/llvmGen/LlvmCodeGen/Data.hs +++ b/compiler/llvmGen/LlvmCodeGen/Data.hs @@ -71,6 +71,7 @@ genLlvmData (sec, Statics lbl xs) = do label <- strCLabel_llvm lbl static <- mapM genData xs lmsec <- llvmSection sec + platform <- getLlvmPlatform let types = map getStatType static strucTy = LMStruct types @@ -79,7 +80,8 @@ genLlvmData (sec, Statics lbl xs) = do struct = Just $ LMStaticStruc static tyAlias link = linkage lbl align = case sec of - Section CString _ -> Just 1 + Section CString _ -> if (platformArch platform == ArchS390X) + then Just 2 else Just 1 _ -> Nothing const = if isSecConstant sec then Constant else Global varDef = LMGlobalVar label tyAlias link lmsec align const diff --git a/compiler/nativeGen/AsmCodeGen.hs b/compiler/nativeGen/AsmCodeGen.hs index 4c883e7185..6b85d388bb 100644 --- a/compiler/nativeGen/AsmCodeGen.hs +++ b/compiler/nativeGen/AsmCodeGen.hs @@ -168,6 +168,7 @@ nativeCodeGen dflags this_mod modLoc h us cmms ArchX86 -> nCG' (x86NcgImpl dflags) ArchX86_64 -> nCG' (x86_64NcgImpl dflags) ArchPPC -> nCG' (ppcNcgImpl dflags) + ArchS390X -> panic "nativeCodeGen: No NCG for S390X" ArchSPARC -> nCG' (sparcNcgImpl dflags) ArchSPARC64 -> panic "nativeCodeGen: No NCG for SPARC64" ArchARM {} -> panic "nativeCodeGen: No NCG for ARM" diff --git a/compiler/nativeGen/RegAlloc/Graph/TrivColorable.hs b/compiler/nativeGen/RegAlloc/Graph/TrivColorable.hs index 5d4fd418c3..773db33293 100644 --- a/compiler/nativeGen/RegAlloc/Graph/TrivColorable.hs +++ b/compiler/nativeGen/RegAlloc/Graph/TrivColorable.hs @@ -119,6 +119,7 @@ trivColorable platform virtualRegSqueeze realRegSqueeze RcInteger conflicts excl ArchAlpha -> panic "trivColorable ArchAlpha" ArchMipseb -> panic "trivColorable ArchMipseb" ArchMipsel -> panic "trivColorable ArchMipsel" + ArchS390X -> panic "trivColorable ArchS390X" ArchJavaScript-> panic "trivColorable ArchJavaScript" ArchUnknown -> panic "trivColorable ArchUnknown") , count2 <- accSqueeze 0 cALLOCATABLE_REGS_INTEGER @@ -149,6 +150,7 @@ trivColorable platform virtualRegSqueeze realRegSqueeze RcFloat conflicts exclus ArchAlpha -> panic "trivColorable ArchAlpha" ArchMipseb -> panic "trivColorable ArchMipseb" ArchMipsel -> panic "trivColorable ArchMipsel" + ArchS390X -> panic "trivColorable ArchS390X" ArchJavaScript-> panic "trivColorable ArchJavaScript" ArchUnknown -> panic "trivColorable ArchUnknown") , count2 <- accSqueeze 0 cALLOCATABLE_REGS_FLOAT @@ -181,6 +183,7 @@ trivColorable platform virtualRegSqueeze realRegSqueeze RcDouble conflicts exclu ArchAlpha -> panic "trivColorable ArchAlpha" ArchMipseb -> panic "trivColorable ArchMipseb" ArchMipsel -> panic "trivColorable ArchMipsel" + ArchS390X -> panic "trivColorable ArchS390X" ArchJavaScript-> panic "trivColorable ArchJavaScript" ArchUnknown -> panic "trivColorable ArchUnknown") , count2 <- accSqueeze 0 cALLOCATABLE_REGS_DOUBLE diff --git a/compiler/nativeGen/RegAlloc/Linear/FreeRegs.hs b/compiler/nativeGen/RegAlloc/Linear/FreeRegs.hs index 5a4f1c65a8..0feddc67d8 100644 --- a/compiler/nativeGen/RegAlloc/Linear/FreeRegs.hs +++ b/compiler/nativeGen/RegAlloc/Linear/FreeRegs.hs @@ -75,6 +75,7 @@ maxSpillSlots dflags ArchX86 -> X86.Instr.maxSpillSlots dflags ArchX86_64 -> X86.Instr.maxSpillSlots dflags ArchPPC -> PPC.Instr.maxSpillSlots dflags + ArchS390X -> panic "maxSpillSlots ArchS390X" ArchSPARC -> SPARC.Instr.maxSpillSlots dflags ArchSPARC64 -> panic "maxSpillSlots ArchSPARC64" ArchARM _ _ _ -> panic "maxSpillSlots ArchARM" diff --git a/compiler/nativeGen/RegAlloc/Linear/Main.hs b/compiler/nativeGen/RegAlloc/Linear/Main.hs index cdaf738d68..eac9194c6a 100644 --- a/compiler/nativeGen/RegAlloc/Linear/Main.hs +++ b/compiler/nativeGen/RegAlloc/Linear/Main.hs @@ -211,6 +211,7 @@ linearRegAlloc dflags entry_ids block_live sccs = case platformArch platform of ArchX86 -> go $ (frInitFreeRegs platform :: X86.FreeRegs) ArchX86_64 -> go $ (frInitFreeRegs platform :: X86_64.FreeRegs) + ArchS390X -> panic "linearRegAlloc ArchS390X" ArchSPARC -> go $ (frInitFreeRegs platform :: SPARC.FreeRegs) ArchSPARC64 -> panic "linearRegAlloc ArchSPARC64" ArchPPC -> go $ (frInitFreeRegs platform :: PPC.FreeRegs) diff --git a/compiler/nativeGen/TargetReg.hs b/compiler/nativeGen/TargetReg.hs index da39b635b2..e0eca9235d 100644 --- a/compiler/nativeGen/TargetReg.hs +++ b/compiler/nativeGen/TargetReg.hs @@ -44,6 +44,7 @@ targetVirtualRegSqueeze platform ArchX86 -> X86.virtualRegSqueeze ArchX86_64 -> X86.virtualRegSqueeze ArchPPC -> PPC.virtualRegSqueeze + ArchS390X -> panic "targetVirtualRegSqueeze ArchS390X" ArchSPARC -> SPARC.virtualRegSqueeze ArchSPARC64 -> panic "targetVirtualRegSqueeze ArchSPARC64" ArchPPC_64 _ -> PPC.virtualRegSqueeze @@ -62,6 +63,7 @@ targetRealRegSqueeze platform ArchX86 -> X86.realRegSqueeze ArchX86_64 -> X86.realRegSqueeze ArchPPC -> PPC.realRegSqueeze + ArchS390X -> panic "targetRealRegSqueeze ArchS390X" ArchSPARC -> SPARC.realRegSqueeze ArchSPARC64 -> panic "targetRealRegSqueeze ArchSPARC64" ArchPPC_64 _ -> PPC.realRegSqueeze @@ -79,6 +81,7 @@ targetClassOfRealReg platform ArchX86 -> X86.classOfRealReg platform ArchX86_64 -> X86.classOfRealReg platform ArchPPC -> PPC.classOfRealReg + ArchS390X -> panic "targetClassOfRealReg ArchS390X" ArchSPARC -> SPARC.classOfRealReg ArchSPARC64 -> panic "targetClassOfRealReg ArchSPARC64" ArchPPC_64 _ -> PPC.classOfRealReg @@ -96,6 +99,7 @@ targetMkVirtualReg platform ArchX86 -> X86.mkVirtualReg ArchX86_64 -> X86.mkVirtualReg ArchPPC -> PPC.mkVirtualReg + ArchS390X -> panic "targetMkVirtualReg ArchS390X" ArchSPARC -> SPARC.mkVirtualReg ArchSPARC64 -> panic "targetMkVirtualReg ArchSPARC64" ArchPPC_64 _ -> PPC.mkVirtualReg @@ -113,6 +117,7 @@ targetRegDotColor platform ArchX86 -> X86.regDotColor platform ArchX86_64 -> X86.regDotColor platform ArchPPC -> PPC.regDotColor + ArchS390X -> panic "targetRegDotColor ArchS390X" ArchSPARC -> SPARC.regDotColor ArchSPARC64 -> panic "targetRegDotColor ArchSPARC64" ArchPPC_64 _ -> PPC.regDotColor diff --git a/configure.ac b/configure.ac index f1c926903c..46e1fdd0f7 100644 --- a/configure.ac +++ b/configure.ac @@ -244,7 +244,7 @@ dnl -------------------------------------------------------------- AC_MSG_CHECKING(whether target supports a registerised ABI) case "$TargetArch" in - i386|x86_64|powerpc|powerpc64|powerpc64le|arm|aarch64) + i386|x86_64|powerpc|powerpc64|powerpc64le|s390x|arm|aarch64) UnregisterisedDefault=NO AC_MSG_RESULT([yes]) ;; @@ -279,7 +279,7 @@ AC_MSG_CHECKING(whether target supports tables next to code) case "$Unregisterised" in NO) case "$TargetArch" in - ia64|powerpc64|powerpc64le) + ia64|powerpc64|powerpc64le|s390x) TablesNextToCodeDefault=NO AC_MSG_RESULT([no]) ;; @@ -308,7 +308,7 @@ AC_SUBST(TablesNextToCode) dnl ** Does target have runtime linker support? dnl -------------------------------------------------------------- case "$target" in - powerpc64-*|powerpc64le-*|powerpc-ibm-aix*) + powerpc64-*|powerpc64le-*|powerpc-ibm-aix*|s390x-ibm-linux) TargetHasRTSLinker=NO ;; *) diff --git a/hadrian/src/Oracles/Flag.hs b/hadrian/src/Oracles/Flag.hs index 93babda794..134edc706e 100644 --- a/hadrian/src/Oracles/Flag.hs +++ b/hadrian/src/Oracles/Flag.hs @@ -59,7 +59,7 @@ platformSupportsSharedLibs = do ghcWithSMP :: Action Bool ghcWithSMP = do - goodArch <- anyTargetArch ["i386", "x86_64", "sparc", "powerpc", "arm"] + goodArch <- anyTargetArch ["i386", "x86_64", "sparc", "powerpc", "arm", "s390x"] ghcUnreg <- flag GhcUnregisterised return $ goodArch && not ghcUnreg diff --git a/includes/CodeGen.Platform.hs b/includes/CodeGen.Platform.hs index 99d774b02c..b108a61c0a 100644 --- a/includes/CodeGen.Platform.hs +++ b/includes/CodeGen.Platform.hs @@ -344,6 +344,42 @@ import Reg # define f30 62 # define f31 63 +#elif defined(MACHREGS_s390x) + +# define r0 0 +# define r1 1 +# define r2 2 +# define r3 3 +# define r4 4 +# define r5 5 +# define r6 6 +# define r7 7 +# define r8 8 +# define r9 9 +# define r10 10 +# define r11 11 +# define r12 12 +# define r13 13 +# define r14 14 +# define r15 15 + +# define f0 16 +# define f1 17 +# define f2 18 +# define f3 19 +# define f4 20 +# define f5 21 +# define f6 22 +# define f7 23 +# define f8 24 +# define f9 25 +# define f10 26 +# define f11 27 +# define f12 28 +# define f13 29 +# define f14 30 +# define f15 31 + #endif callerSaves :: GlobalReg -> Bool @@ -630,7 +666,8 @@ haveRegBase = False globalRegMaybe :: GlobalReg -> Maybe RealReg #if defined(MACHREGS_i386) || defined(MACHREGS_x86_64) \ || defined(MACHREGS_sparc) || defined(MACHREGS_powerpc) \ - || defined(MACHREGS_arm) || defined(MACHREGS_aarch64) + || defined(MACHREGS_arm) || defined(MACHREGS_aarch64) \ + || defined(MACHREGS_s390x) # if defined(REG_Base) globalRegMaybe BaseReg = Just (RealRegSingle REG_Base) # endif diff --git a/includes/stg/MachRegs.h b/includes/stg/MachRegs.h index 0afc88152e..ea1125bbf8 100644 --- a/includes/stg/MachRegs.h +++ b/includes/stg/MachRegs.h @@ -589,6 +589,78 @@ the stack. See Note [Overlapping global registers] for implications. #define REG_D3 d14 #define REG_D4 d15 +/* ----------------------------------------------------------------------------- + The s390x register mapping + + Register | Role(s) | Call effect + ------------+-------------------------------------+----------------- + r0,r1 | - | caller-saved + r2 | Argument / return value | caller-saved + r3,r4,r5 | Arguments | caller-saved + r6 | Argument | callee-saved + r7...r11 | - | callee-saved + r12 | (Commonly used as GOT pointer) | callee-saved + r13 | (Commonly used as literal pool pointer) | callee-saved + r14 | Return address | caller-saved + r15 | Stack pointer | callee-saved + f0 | Argument / return value | caller-saved + f2,f4,f6 | Arguments | caller-saved + f1,f3,f5,f7 | - | caller-saved + f8...f15 | - | callee-saved + v0...v31 | - | caller-saved + + Each general purpose register r0 through r15 as well as each floating-point + register f0 through f15 is 64 bits wide. Each vector register v0 through v31 + is 128 bits wide. + + Note, the vector registers v0 through v15 overlap with the floating-point + registers f0 through f15. + + -------------------------------------------------------------------------- */ + +#elif defined(MACHREGS_s390x) + +#define REG(x) __asm__("%" #x) + +#define REG_Base r7 +#define REG_Sp r8 +#define REG_Hp r10 +#define REG_R1 r11 +#define REG_R2 r12 +#define REG_R3 r13 +#define REG_R4 r6 +#define REG_R5 r2 +#define REG_R6 r3 +#define REG_R7 r4 +#define REG_R8 r5 +#define REG_SpLim r9 +#define REG_MachSp r15 + +#define REG_F1 f8 +#define REG_F2 f9 +#define REG_F3 f10 +#define REG_F4 f11 +#define REG_F5 f0 +#define REG_F6 f1 + +#define REG_D1 f12 +#define REG_D2 f13 +#define REG_D3 f14 +#define REG_D4 f15 +#define REG_D5 f2 +#define REG_D6 f3 + +#define CALLER_SAVES_R5 +#define CALLER_SAVES_R6 +#define CALLER_SAVES_R7 +#define CALLER_SAVES_R8 + +#define CALLER_SAVES_F5 +#define CALLER_SAVES_F6 + +#define CALLER_SAVES_D5 +#define CALLER_SAVES_D6 + #else #error Cannot find platform to give register info for diff --git a/includes/stg/MachRegsForHost.h b/includes/stg/MachRegsForHost.h index 135c7974bd..3597b2be90 100644 --- a/includes/stg/MachRegsForHost.h +++ b/includes/stg/MachRegsForHost.h @@ -67,6 +67,10 @@ #define MACHREGS_darwin 1 #endif +#if defined(s390x_HOST_ARCH) +#define MACHREGS_s390x 1 +#endif + #endif #include "MachRegs.h" diff --git a/includes/stg/SMP.h b/includes/stg/SMP.h index 4be11d1f64..2d6a220a9e 100644 --- a/includes/stg/SMP.h +++ b/includes/stg/SMP.h @@ -336,6 +336,8 @@ write_barrier(void) { #elif defined(powerpc_HOST_ARCH) || defined(powerpc64_HOST_ARCH) \ || defined(powerpc64le_HOST_ARCH) __asm__ __volatile__ ("lwsync" : : : "memory"); +#elif defined(s390x_HOST_ARCH) + __asm__ __volatile__ ("" : : : "memory"); #elif defined(sparc_HOST_ARCH) /* Sparc in TSO mode does not require store/store barriers. */ __asm__ __volatile__ ("" : : : "memory"); @@ -357,6 +359,8 @@ store_load_barrier(void) { #elif defined(powerpc_HOST_ARCH) || defined(powerpc64_HOST_ARCH) \ || defined(powerpc64le_HOST_ARCH) __asm__ __volatile__ ("sync" : : : "memory"); +#elif defined(s390x_HOST_ARCH) + __asm__ __volatile__ ("bcr 14,0" : : : "memory"); #elif defined(sparc_HOST_ARCH) __asm__ __volatile__ ("membar #StoreLoad" : : : "memory"); #elif defined(arm_HOST_ARCH) @@ -379,6 +383,8 @@ load_load_barrier(void) { #elif defined(powerpc_HOST_ARCH) || defined(powerpc64_HOST_ARCH) \ || defined(powerpc64le_HOST_ARCH) __asm__ __volatile__ ("lwsync" : : : "memory"); +#elif defined(s390x_HOST_ARCH) + __asm__ __volatile__ ("" : : : "memory"); #elif defined(sparc_HOST_ARCH) /* Sparc in TSO mode does not require load/load barriers. */ __asm__ __volatile__ ("" : : : "memory"); diff --git a/libraries/ghc-boot/GHC/Platform.hs b/libraries/ghc-boot/GHC/Platform.hs index 8e4ae5f4b9..341b551fc5 100644 --- a/libraries/ghc-boot/GHC/Platform.hs +++ b/libraries/ghc-boot/GHC/Platform.hs @@ -106,6 +106,7 @@ data Arch | ArchPPC_64 { ppc_64ABI :: PPC_64ABI } + | ArchS390X | ArchSPARC | ArchSPARC64 | ArchARM @@ -145,6 +146,7 @@ stringEncodeArch = \case ArchPPC_64 { ppc_64ABI = abi } -> case abi of ELF_V1 -> "powerpc64" ELF_V2 -> "powerpc64le" + ArchS390X -> "s390x" ArchSPARC -> "sparc" ArchSPARC64 -> "sparc64" ArchARM { armISA = isa, armISAExt = _, armABI = _ } -> "arm" ++ vsuf diff --git a/libraries/ghci/GHCi/InfoTable.hsc b/libraries/ghci/GHCi/InfoTable.hsc index ab13485e28..587e39bbed 100644 --- a/libraries/ghci/GHCi/InfoTable.hsc +++ b/libraries/ghci/GHCi/InfoTable.hsc @@ -76,6 +76,7 @@ data Arch = ArchSPARC | ArchARM64 | ArchPPC64 | ArchPPC64LE + | ArchS390X | ArchUnknown deriving Show @@ -99,6 +100,8 @@ platform = ArchPPC64 #elif defined(powerpc64le_HOST_ARCH) ArchPPC64LE +#elif defined(s390x_HOST_ARCH) + ArchS390X #else # if defined(TABLES_NEXT_TO_CODE) # error Unimplemented architecture @@ -268,6 +271,20 @@ mkJumpToAddr a = case platform of 0x618C0000 .|. lo16 w32, 0x7D8903A6, 0x4E800420 ] + ArchS390X -> + -- Let 0xAABBCCDDEEFFGGHH be the address to jump to. + -- The following code loads the address into scratch + -- register r1 and jumps to it. + -- + -- 0: C0 1E AA BB CC DD llihf %r1,0xAABBCCDD + -- 6: C0 19 EE FF GG HH iilf %r1,0xEEFFGGHH + -- 12: 07 F1 br %r1 + + let w64 = fromIntegral (funPtrToInt a) :: Word64 + in Left [ 0xC0, 0x1E, byte7 w64, byte6 w64, byte5 w64, byte4 w64, + 0xC0, 0x19, byte3 w64, byte2 w64, byte1 w64, byte0 w64, + 0x07, 0xF1 ] + -- This code must not be called. You either need to -- add your architecture as a distinct case or -- use non-TABLES_NEXT_TO_CODE mode diff --git a/llvm-targets b/llvm-targets index 8f5717d98b..9cf969822c 100644 --- a/llvm-targets +++ b/llvm-targets @@ -33,6 +33,7 @@ ,("powerpc64le-unknown-linux-gnu", ("e-m:e-i64:64-n32:64", "ppc64le", "")) ,("powerpc64le-unknown-linux-musl", ("e-m:e-i64:64-n32:64", "ppc64le", "")) ,("powerpc64le-unknown-linux", ("e-m:e-i64:64-n32:64", "ppc64le", "")) +,("s390x-ibm-linux", ("E-m:e-i1:8:16-i8:8:16-i64:64-f128:64-a:8:16-n32:64", "z10", "")) ,("i386-apple-darwin", ("e-m:o-p:32:32-f64:32:64-f80:128-n8:16:32-S128", "yonah", "")) ,("x86_64-apple-darwin", ("e-m:o-i64:64-f80:128-n8:16:32:64-S128", "core2", "")) ,("armv7-apple-ios", ("e-m:o-p:32:32-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32", "generic", "")) diff --git a/mk/config.mk.in b/mk/config.mk.in index 8bbfde2e26..05ad6ad199 100644 --- a/mk/config.mk.in +++ b/mk/config.mk.in @@ -192,7 +192,7 @@ ifeq "$(TargetArch_CPP)" "arm" # We don't support load/store barriers pre-ARMv7. See #10433. ArchSupportsSMP=$(if $(filter $(ARM_ISA),ARMv5 ARMv6),NO,YES) else -ArchSupportsSMP=$(strip $(patsubst $(TargetArch_CPP), YES, $(findstring $(TargetArch_CPP), i386 x86_64 sparc powerpc powerpc64 powerpc64le aarch64))) +ArchSupportsSMP=$(strip $(patsubst $(TargetArch_CPP), YES, $(findstring $(TargetArch_CPP), i386 x86_64 sparc powerpc powerpc64 powerpc64le s390x aarch64))) endif # The THREADED_RTS requires `BaseReg` to be in a register and the @@ -365,7 +365,7 @@ FFIIncludeDir=@FFIIncludeDir@ # GHC needs arch-specific tweak at least in # rts/Libdw.c:set_initial_registers() -GhcRtsWithLibdw=$(strip $(if $(filter $(TargetArch_CPP),i386 x86_64),@UseLibdw@,NO)) +GhcRtsWithLibdw=$(strip $(if $(filter $(TargetArch_CPP),i386 x86_64 s390x),@UseLibdw@,NO)) ################################################################################ # diff --git a/rts/Capability.h b/rts/Capability.h index 2a5f127793..0833006b0c 100644 --- a/rts/Capability.h +++ b/rts/Capability.h @@ -160,7 +160,9 @@ struct Capability_ { } // typedef Capability is defined in RtsAPI.h // We never want a Capability to overlap a cache line with anything // else, so round it up to a cache line size: -#if !defined(mingw32_HOST_OS) +#if defined(s390x_HOST_ARCH) + ATTRIBUTE_ALIGNED(256) +#elif !defined(mingw32_HOST_OS) ATTRIBUTE_ALIGNED(64) #endif ; diff --git a/rts/Libdw.c b/rts/Libdw.c index 33a40a1f37..d45d9d0e5d 100644 --- a/rts/Libdw.c +++ b/rts/Libdw.c @@ -330,6 +330,35 @@ static bool set_initial_registers(Dwfl_Thread *thread, ); return dwfl_thread_state_registers(thread, 0, 9, regs); } +#elif defined(s390x_HOST_ARCH) +static bool set_initial_registers(Dwfl_Thread *thread, + void *arg STG_UNUSED) { + Dwarf_Word regs[32]; + __asm__ ("stmg %%r0,%%r15,0(%0)\n\t" + "std %%f0, 128(0,%0)\n\t" + "std %%f2, 136(0,%0)\n\t" + "std %%f4, 144(0,%0)\n\t" + "std %%f6, 152(0,%0)\n\t" + "std %%f1, 160(0,%0)\n\t" + "std %%f3, 168(0,%0)\n\t" + "std %%f5, 176(0,%0)\n\t" + "std %%f7, 184(0,%0)\n\t" + "std %%f8, 192(0,%0)\n\t" + "std %%f10, 200(0,%0)\n\t" + "std %%f12, 208(0,%0)\n\t" + "std %%f14, 216(0,%0)\n\t" + "std %%f9, 224(0,%0)\n\t" + "std %%f11, 232(0,%0)\n\t" + "std %%f13, 240(0,%0)\n\t" + "std %%f15, 248(0,%0)\n\t" + "larl %%r0,0\n\t" + "stg %%r0, 112(0,%0)\n\t" + : /* no output */ + :"r" (®s[0]) /* input */ + :"%r0" /* clobbered */ + ); + return dwfl_thread_state_registers(thread, 0, 32, regs); +} #else # error "Please implement set_initial_registers() for your arch" #endif diff --git a/rts/StgCRunAsm.S b/rts/StgCRunAsm.S index 1dd74d3652..946f5775ea 100644 --- a/rts/StgCRunAsm.S +++ b/rts/StgCRunAsm.S @@ -180,4 +180,96 @@ StgReturn: blr # endif // aix_HOST_OS + +#elif defined(s390x_HOST_ARCH) +# define STACK_FRAME_SIZE (RESERVED_C_STACK_BYTES+160) + .text + .align 8 + .globl StgRun + .type StgRun, @function +StgRun: + .cfi_startproc + /* save callee-saved registers */ + stmg %r6,%r14,16(%r15) + std %f8, 88(%r15) + std %f9, 96(%r15) + std %f10, 104(%r15) + std %f11, 112(%r15) + std %f12, 120(%r15) + std %f13, 128(%r15) + std %f14, 136(%r15) + std %f15, 144(%r15) + .cfi_offset 6, -144 + .cfi_offset 7, -136 + .cfi_offset 8, -128 + .cfi_offset 9, -120 + .cfi_offset 10, -112 + .cfi_offset 11, -104 + .cfi_offset 12, -96 + .cfi_offset 13, -88 + .cfi_offset 14, -80 + .cfi_offset 15, -72 + .cfi_offset 24, -64 + .cfi_offset 28, -56 + .cfi_offset 25, -48 + .cfi_offset 29, -40 + .cfi_offset 26, -32 + .cfi_offset 30, -24 + .cfi_offset 27, -16 + .cfi_offset 31, -8 + /* allocate stack frame */ + aghi %r15,-STACK_FRAME_SIZE + .cfi_def_cfa_offset -(STACK_FRAME_SIZE+160) + /* set STGs BaseReg from S390Xs r3 */ + lgr %r7,%r3 + /* jump to STG function */ + br %r2 + .cfi_endproc + .size StgRun, .-StgRun + + .text + .align 8 + .globl StgReturn + .type StgReturn, @function +StgReturn: + .cfi_startproc + /* set return value from STGs R1 (S390Xs r11) */ + lgr %r2,%r11 + /* deallocate stack frame */ + aghi %r15,STACK_FRAME_SIZE + .cfi_def_cfa_offset (STACK_FRAME_SIZE+160) + /* restore callee-saved registers */ + lmg %r6,%r14, 16(%r15) + ld %f8, 88(%r15) + ld %f9, 96(%r15) + ld %f10, 104(%r15) + ld %f11, 112(%r15) + ld %f12, 120(%r15) + ld %f13, 128(%r15) + ld %f14, 136(%r15) + ld %f15, 144(%r15) + .cfi_restore 6 + .cfi_restore 7 + .cfi_restore 8 + .cfi_restore 9 + .cfi_restore 10 + .cfi_restore 11 + .cfi_restore 12 + .cfi_restore 13 + .cfi_restore 14 + .cfi_restore 24 + .cfi_restore 28 + .cfi_restore 25 + .cfi_restore 29 + .cfi_restore 26 + .cfi_restore 30 + .cfi_restore 27 + .cfi_restore 31 + .cfi_def_cfa 15, 160 + /* jump back to caller of StgRun() */ + br %r14 + .cfi_endproc + .size StgReturn, .-StgReturn + + .section .note.GNU-stack,"",@progbits #endif diff --git a/rts/ghc.mk b/rts/ghc.mk index c07cfaec86..dca22fb733 100644 --- a/rts/ghc.mk +++ b/rts/ghc.mk @@ -55,7 +55,7 @@ ifneq "$(findstring $(TargetArch_CPP), i386 powerpc powerpc64)" "" rts_S_SRCS += rts/AdjustorAsm.S endif # this matches substrings of powerpc64le, including "powerpc" and "powerpc64" -ifneq "$(findstring $(TargetArch_CPP), powerpc64le)" "" +ifneq "$(findstring $(TargetArch_CPP), powerpc64le s390x)" "" # unregisterised builds use the mini interpreter ifneq "$(GhcUnregisterised)" "YES" rts_S_SRCS += rts/StgCRunAsm.S diff --git a/rts/linker/Elf.c b/rts/linker/Elf.c index 0882f8d349..79786ccd3d 100644 --- a/rts/linker/Elf.c +++ b/rts/linker/Elf.c @@ -391,6 +391,12 @@ ocVerifyImage_ELF ( ObjectCode* oc ) oc->fileName); return 0; #endif +#if defined(EM_S390) + case EM_S390: IF_DEBUG(linker,debugBelch( "s390" )); + errorBelch("%s: RTS linker not implemented on s390", + oc->fileName); + return 0; +#endif #if defined(EM_X86_64) case EM_X86_64: IF_DEBUG(linker,debugBelch( "x86_64" )); break; #elif defined(EM_AMD64) diff --git a/rts/rts.cabal.in b/rts/rts.cabal.in index 99f1e7296d..30c829ad42 100644 --- a/rts/rts.cabal.in +++ b/rts/rts.cabal.in @@ -370,7 +370,7 @@ library if arch(i386) || arch(powerpc) || arch(powerpc64) asm-sources: AdjustorAsm.S - if arch(powerpc) || arch(powerpc64) || arch(powerpc64le) + if arch(powerpc) || arch(powerpc64) || arch(powerpc64le) || arch(s390x) asm-sources: StgCRunAsm.S c-sources: Adjustor.c diff --git a/utils/llvm-targets/gen-data-layout.sh b/utils/llvm-targets/gen-data-layout.sh index a73da499f3..4f4a1ef079 100755 --- a/utils/llvm-targets/gen-data-layout.sh +++ b/utils/llvm-targets/gen-data-layout.sh @@ -70,6 +70,8 @@ TARGETS=( "powerpc64le-unknown-linux-gnu" "powerpc64le-unknown-linux-musl" "powerpc64le-unknown-linux" + # Linux s390x + "s390x-ibm-linux" ######################### # Darwin |