From c6bede69443a9f40b0504cee83d9b2c5e9b8163b Mon Sep 17 00:00:00 2001 From: Ben Gamari Date: Wed, 26 Jan 2022 20:43:22 -0500 Subject: rts: Rip out SPARC support --- libraries/ghci/GHCi/InfoTable.hsc | 22 -------- rts/StgCRun.c | 75 +-------------------------- rts/adjustor/NativeSparc.c | 106 -------------------------------------- rts/include/stg/SMP.h | 3 -- rts/linker/Elf.c | 75 ++++----------------------- rts/rts.cabal.in | 2 - rts/sm/GCTDecl.h | 20 ------- 7 files changed, 10 insertions(+), 293 deletions(-) delete mode 100644 rts/adjustor/NativeSparc.c diff --git a/libraries/ghci/GHCi/InfoTable.hsc b/libraries/ghci/GHCi/InfoTable.hsc index 9cc9ac1557..d92a2f0fbb 100644 --- a/libraries/ghci/GHCi/InfoTable.hsc +++ b/libraries/ghci/GHCi/InfoTable.hsc @@ -67,28 +67,6 @@ funPtrToInt (FunPtr a) = I## (addr2Int## a) mkJumpToAddr :: MonadFail m => EntryFunPtr-> m ItblCodes mkJumpToAddr a = case hostPlatformArch of - ArchSPARC -> pure $ - -- After some consideration, we'll try this, where - -- 0x55555555 stands in for the address to jump to. - -- According to rts/include/rts/MachRegs.h, %g3 is very - -- likely indeed to be baggable. - -- - -- 0000 07155555 sethi %hi(0x55555555), %g3 - -- 0004 8610E155 or %g3, %lo(0x55555555), %g3 - -- 0008 81C0C000 jmp %g3 - -- 000c 01000000 nop - - let w32 = fromIntegral (funPtrToInt a) - - hi22, lo10 :: Word32 -> Word32 - lo10 x = x .&. 0x3FF - hi22 x = (x `shiftR` 10) .&. 0x3FFFF - - in Right [ 0x07000000 .|. (hi22 w32), - 0x8610E000 .|. (lo10 w32), - 0x81C0C000, - 0x01000000 ] - ArchPPC -> pure $ -- We'll use r12, for no particular reason. -- 0xDEADBEEF stands for the address: diff --git a/rts/StgCRun.c b/rts/StgCRun.c index 25a931994d..8e536ad6c2 100644 --- a/rts/StgCRun.c +++ b/rts/StgCRun.c @@ -36,7 +36,7 @@ #define ENABLE_UNWINDING #endif -#if defined(sparc_HOST_ARCH) || defined(USE_MINIINTERPRETER) +#if defined(USE_MINIINTERPRETER) /* include Stg.h first because we want real machine regs in here: we * have to get the value of R1 back from Stg land to C land intact. */ @@ -564,79 +564,6 @@ StgRunIsImplementedInAssembler(void) #endif /* x86-64 */ -/* ----------------------------------------------------------------------------- - Sparc architecture - - -- - OLD COMMENT from GHC-3.02: - - We want tailjumps to be calls, because `call xxx' is the only Sparc - branch that allows an arbitrary label as a target. (Gcc's ``goto - *target'' construct ends up loading the label into a register and - then jumping, at the cost of two extra instructions for the 32-bit - load.) - - When entering the threaded world, we stash our return address in a - known location so that \tr{%i7} is available as an extra - callee-saves register. Of course, we have to restore this when - coming out of the threaded world. - - I hate this god-forsaken architecture. Since the top of the - reserved stack space is used for globals and the bottom is reserved - for outgoing arguments, we have to stick our return address - somewhere in the middle. Currently, I'm allowing 100 extra - outgoing arguments beyond the first 6. --JSM - - Updated info (GHC 4.06): we don't appear to use %i7 any more, so - I'm not sure whether we still need to save it. Incedentally, what - does the last paragraph above mean when it says "the top of the - stack is used for globals"? What globals? --SDM - - Updated info (GHC 4.08.2): not saving %i7 any more (see below). - -------------------------------------------------------------------------- */ - -#if defined(sparc_HOST_ARCH) - -StgRegTable * -StgRun(StgFunPtr f, StgRegTable *basereg) { - - unsigned char space[RESERVED_C_STACK_BYTES]; -#if 0 - register void *i7 __asm__("%i7"); - ((void **)(space))[100] = i7; -#endif - f(); - __asm__ volatile ( - ".align 4\n" - ".global " STG_RETURN "\n" - STG_RETURN ":" - : : "p" (space) : "l0","l1","l2","l3","l4","l5","l6","l7"); - /* we tell the C compiler that l0-l7 are clobbered on return to - * StgReturn, otherwise it tries to use these to save eg. the - * address of space[100] across the call. The correct thing - * to do would be to save all the callee-saves regs, but we - * can't be bothered to do that. - * - * We also explicitly mark space as used since gcc eliminates it - * otherwise. - * - * The code that gcc generates for this little fragment is now - * terrible. We could do much better by coding it directly in - * assembler. - */ -#if 0 - /* updated 4.08.2: we don't save %i7 in the middle of the reserved - * space any more, since gcc tries to save its address across the - * call to f(), this gets clobbered in STG land and we end up - * dereferencing a bogus pointer in StgReturn. - */ - __asm__ volatile ("ld %1,%0" - : "=r" (i7) : "m" (((void **)(space))[100])); -#endif - return (StgRegTable *)R1.i; -} - -#endif /* ----------------------------------------------------------------------------- PowerPC architecture diff --git a/rts/adjustor/NativeSparc.c b/rts/adjustor/NativeSparc.c deleted file mode 100644 index 52e023dcbe..0000000000 --- a/rts/adjustor/NativeSparc.c +++ /dev/null @@ -1,106 +0,0 @@ -/* ----------------------------------------------------------------------------- - * SPARC architecture adjustor thunk logic. - * ---------------------------------------------------------------------------*/ - -#include "rts/PosixSource.h" -#include "Rts.h" - -#include "RtsUtils.h" -#include "StablePtr.h" - -void* -createAdjustor(int cconv, StgStablePtr hptr, - StgFunPtr wptr, - char *typeString STG_UNUSED - ) -{ - switch (cconv) - { - case 1: /* _ccall */ - /* Magic constant computed by inspecting the code length of the following - assembly language snippet (offset and machine code prefixed): - - <00>: 9C23A008 sub %sp, 8, %sp ! make room for %o4/%o5 in caller's frame - <04>: DA23A060 st %o5, [%sp + 96] ! shift registers by 2 positions - <08>: D823A05C st %o4, [%sp + 92] - <0C>: 9A10000B mov %o3, %o5 - <10>: 9810000A mov %o2, %o4 - <14>: 96100009 mov %o1, %o3 - <18>: 94100008 mov %o0, %o2 - <1C>: 13000000 sethi %hi(wptr), %o1 ! load up wptr (1 of 2) - <20>: 11000000 sethi %hi(hptr), %o0 ! load up hptr (1 of 2) - <24>: 81C26000 jmp %o1 + %lo(wptr) ! jump to wptr (load 2 of 2) - <28>: 90122000 or %o0, %lo(hptr), %o0 ! load up hptr (2 of 2, delay slot) - <2C> 00000000 ! place for getting hptr back easily - - ccall'ing on SPARC is easy, because we are quite lucky to push a - multiple of 8 bytes (1 word hptr + 1 word dummy arg) in front of the - existing arguments (note that %sp must stay double-word aligned at - all times, see ABI spec at http://www.sparc.org/standards/psABI3rd.pdf). - To do this, we extend the *caller's* stack frame by 2 words and shift - the output registers used for argument passing (%o0 - %o5, we are a *leaf* - procedure because of the tail-jump) by 2 positions. This makes room in - %o0 and %o1 for the additional arguments, namely hptr and a dummy (used - for destination addr of jump on SPARC, return address on x86, ...). This - shouldn't cause any problems for a C-like caller: alloca is implemented - similarly, and local variables should be accessed via %fp, not %sp. In a - nutshell: This should work! (Famous last words! :-) - */ - { - ExecPage *page = allocateExecPage(); - unsigned long *const adj_code = (unsigned long *) page; - - adj_code[ 0] = 0x9C23A008UL; /* sub %sp, 8, %sp */ - adj_code[ 1] = 0xDA23A060UL; /* st %o5, [%sp + 96] */ - adj_code[ 2] = 0xD823A05CUL; /* st %o4, [%sp + 92] */ - adj_code[ 3] = 0x9A10000BUL; /* mov %o3, %o5 */ - adj_code[ 4] = 0x9810000AUL; /* mov %o2, %o4 */ - adj_code[ 5] = 0x96100009UL; /* mov %o1, %o3 */ - adj_code[ 6] = 0x94100008UL; /* mov %o0, %o2 */ - adj_code[ 7] = 0x13000000UL; /* sethi %hi(wptr), %o1 */ - adj_code[ 7] |= ((unsigned long)wptr) >> 10; - adj_code[ 8] = 0x11000000UL; /* sethi %hi(hptr), %o0 */ - adj_code[ 8] |= ((unsigned long)hptr) >> 10; - adj_code[ 9] = 0x81C26000UL; /* jmp %o1 + %lo(wptr) */ - adj_code[ 9] |= ((unsigned long)wptr) & 0x000003FFUL; - adj_code[10] = 0x90122000UL; /* or %o0, %lo(hptr), %o0 */ - adj_code[10] |= ((unsigned long)hptr) & 0x000003FFUL; - - adj_code[11] = (unsigned long)hptr; - - freezeExecPage(page); - - /* flush cache */ - asm("flush %0" : : "r" (adj_code )); - asm("flush %0" : : "r" (adj_code + 2)); - asm("flush %0" : : "r" (adj_code + 4)); - asm("flush %0" : : "r" (adj_code + 6)); - asm("flush %0" : : "r" (adj_code + 10)); - - /* max. 5 instructions latency, and we need at >= 1 for returning */ - asm("nop"); - asm("nop"); - asm("nop"); - asm("nop"); - - return page; - } - - default: - barf("createAdjustor: Unsupported calling convention"); - } -} - -void -freeHaskellFunctionPtr(void* ptr) -{ - if ( *(unsigned long*)ptr != 0x9C23A008UL ) { - errorBelch("freeHaskellFunctionPtr: not for me, guv! %p\n", ptr); - return; - } - - /* Free the stable pointer first..*/ - freeStablePtr(*((StgStablePtr*)((unsigned long*)ptr + 11))); - - freeExecPage(ptr); -} diff --git a/rts/include/stg/SMP.h b/rts/include/stg/SMP.h index 282680c772..8aaf706f59 100644 --- a/rts/include/stg/SMP.h +++ b/rts/include/stg/SMP.h @@ -390,9 +390,6 @@ write_barrier(void) { __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"); #elif defined(arm_HOST_ARCH) || defined(aarch64_HOST_ARCH) __asm__ __volatile__ ("dmb st" : : : "memory"); #elif defined(riscv64_HOST_ARCH) diff --git a/rts/linker/Elf.c b/rts/linker/Elf.c index 06afae631d..c5d009639e 100644 --- a/rts/linker/Elf.c +++ b/rts/linker/Elf.c @@ -87,9 +87,7 @@ */ #define X86_64_ELF_NONPIC_HACK (!RtsFlags.MiscFlags.linkerAlwaysPic) -#if defined(sparc_HOST_ARCH) -# define ELF_TARGET_SPARC /* Used inside */ -#elif defined(i386_HOST_ARCH) +#if defined(i386_HOST_ARCH) # define ELF_TARGET_386 /* Used inside */ #elif defined(x86_64_HOST_ARCH) # define ELF_TARGET_X64_64 @@ -1463,8 +1461,7 @@ do_Elf_Rel_relocations ( ObjectCode* oc, char* ehdrC, return 1; } -/* Do ELF relocations for which explicit addends are supplied. - sparc-solaris relocations appear to be of this form. */ +/* Do ELF relocations for which explicit addends are supplied. */ static int do_Elf_Rela_relocations ( ObjectCode* oc, char* ehdrC, Elf_Shdr* shdr, int shnum ) @@ -1481,8 +1478,7 @@ do_Elf_Rela_relocations ( ObjectCode* oc, char* ehdrC, #if defined(SHN_XINDEX) Elf_Word* shndx_table = get_shndx_table((Elf_Ehdr*)ehdrC); #endif -#if defined(DEBUG) || defined(sparc_HOST_ARCH) || defined(powerpc_HOST_ARCH) \ - || defined(x86_64_HOST_ARCH) +#if defined(DEBUG) || defined(powerpc_HOST_ARCH) || defined(x86_64_HOST_ARCH) /* This #if def only serves to avoid unused-var warnings. */ Elf_Addr targ = (Elf_Addr) oc->sections[target_shndx].start; #endif @@ -1500,24 +1496,19 @@ do_Elf_Rela_relocations ( ObjectCode* oc, char* ehdrC, } for (j = 0; j < nent; j++) { -#if defined(DEBUG) || defined(sparc_HOST_ARCH) || defined(powerpc_HOST_ARCH) \ - || defined(x86_64_HOST_ARCH) +#if defined(DEBUG) || defined(powerpc_HOST_ARCH) || defined(x86_64_HOST_ARCH) /* This #if def only serves to avoid unused-var warnings. */ Elf_Addr offset = rtab[j].r_offset; Elf_Addr P = targ + offset; Elf_Addr A = rtab[j].r_addend; #endif -#if defined(sparc_HOST_ARCH) || defined(powerpc_HOST_ARCH) \ - || defined(x86_64_HOST_ARCH) +#if defined(powerpc_HOST_ARCH) || defined(x86_64_HOST_ARCH) Elf_Addr value; #endif Elf_Addr info = rtab[j].r_info; Elf_Addr S; void* S_tmp; -# if defined(sparc_HOST_ARCH) - Elf_Word* pP = (Elf_Word*)P; - Elf_Word w1, w2; -# elif defined(powerpc_HOST_ARCH) +# if defined(powerpc_HOST_ARCH) Elf_Sword delta; # endif @@ -1587,66 +1578,18 @@ do_Elf_Rela_relocations ( ObjectCode* oc, char* ehdrC, IF_DEBUG(linker_verbose,debugBelch("`%s' resolves to %p\n", symbol, (void*)S)); } -#if defined(DEBUG) || defined(sparc_HOST_ARCH) || defined(powerpc_HOST_ARCH) \ - || defined(x86_64_HOST_ARCH) +#if defined(DEBUG) || defined(powerpc_HOST_ARCH) || defined(x86_64_HOST_ARCH) IF_DEBUG(linker_verbose,debugBelch("Reloc: P = %p S = %p A = %p\n", (void*)P, (void*)S, (void*)A )); checkProddableBlock(oc, (void*)P, sizeof(Elf_Word)); #endif -#if defined(sparc_HOST_ARCH) || defined(powerpc_HOST_ARCH) \ - || defined(x86_64_HOST_ARCH) +#if defined(powerpc_HOST_ARCH) || defined(x86_64_HOST_ARCH) value = S + A; #endif switch (ELF_R_TYPE(info)) { -# if defined(sparc_HOST_ARCH) - case R_SPARC_WDISP30: - w1 = *pP & 0xC0000000; - w2 = (Elf_Word)((value - P) >> 2); - CHECK((w2 & 0xC0000000) == 0); - w1 |= w2; - *pP = w1; - break; - case R_SPARC_HI22: - w1 = *pP & 0xFFC00000; - w2 = (Elf_Word)(value >> 10); - CHECK((w2 & 0xFFC00000) == 0); - w1 |= w2; - *pP = w1; - break; - case R_SPARC_LO10: - w1 = *pP & ~0x3FF; - w2 = (Elf_Word)(value & 0x3FF); - CHECK((w2 & ~0x3FF) == 0); - w1 |= w2; - *pP = w1; - break; - - /* According to the Sun documentation: - R_SPARC_UA32 - This relocation type resembles R_SPARC_32, except it refers to an - unaligned word. That is, the word to be relocated must be treated - as four separate bytes with arbitrary alignment, not as a word - aligned according to the architecture requirements. - */ - case R_SPARC_UA32: - w2 = (Elf_Word)value; - - // SPARC doesn't do misaligned writes of 32 bit words, - // so we have to do this one byte-at-a-time. - char *pPc = (char*)pP; - pPc[0] = (char) ((Elf_Word)(w2 & 0xff000000) >> 24); - pPc[1] = (char) ((Elf_Word)(w2 & 0x00ff0000) >> 16); - pPc[2] = (char) ((Elf_Word)(w2 & 0x0000ff00) >> 8); - pPc[3] = (char) ((Elf_Word)(w2 & 0x000000ff)); - break; - - case R_SPARC_32: - w2 = (Elf_Word)value; - *pP = w2; - break; -# elif defined(powerpc_HOST_ARCH) +# if defined(powerpc_HOST_ARCH) case R_PPC_ADDR16_LO: *(Elf32_Half*) P = value; break; diff --git a/rts/rts.cabal.in b/rts/rts.cabal.in index e7d5c4a7c7..ec907cd10b 100644 --- a/rts/rts.cabal.in +++ b/rts/rts.cabal.in @@ -465,8 +465,6 @@ library c-sources: adjustor/NativePowerPC.c if arch(ia64) c-sources: adjustor/NativeIA64.c - if arch(sparc) - c-sources: adjustor/NativeSparc.c -- Use assembler STG entrypoint on archictures where it is used if arch(ppc) || arch(ppc64) || arch(s390x) || arch(riscv64) diff --git a/rts/sm/GCTDecl.h b/rts/sm/GCTDecl.h index e740392c15..2fbe1894f8 100644 --- a/rts/sm/GCTDecl.h +++ b/rts/sm/GCTDecl.h @@ -85,26 +85,6 @@ extern __thread gc_thread* gct; /* -------------------------------------------------------------------------- */ -/* Next up: On SPARC we can't pin gct to a register. Names like %l1 - are just offsets into the register window, which change on each - function call. - - There are eight global (non-window) registers, but they're used for other - purposes: - - %g0 -- always zero - %g1 -- volatile over function calls, used by the linker - %g2-%g3 -- used as scratch regs by the C compiler (caller saves) - %g4 -- volatile over function calls, used by the linker - %g5-%g7 -- reserved by the OS -*/ -#elif defined(sparc_HOST_ARCH) -extern __thread gc_thread* gct; -#define SET_GCT(to) gct = (to) -#define DECLARE_GCT __thread gc_thread* gct; - -/* -------------------------------------------------------------------------- */ - /* Next up: generally, if REG_Base is defined and we're *not* using i386, then actually declare the needed register. The catch for i386 here is that REG_Base is %ebx, but that is also used for -fPIC, so -- cgit v1.2.1