Commit 0ac3ecb8 authored by jan.koester's avatar jan.koester
Browse files

Port systempp to 32-bit PowerPC (e500v2, big endian)

New architecture src/linux/arch/powerpc: syscalls (sc, CR0.SO errors,
register-pair 64-bit arguments), crt1/Scrt1/crti/crtn/dlstart, clone,
setjmp/sigsetjmp, signal trampolines, atomics, TLS variant I (r2 =
tcb end + 0x7000), DWARF unwinder registers, 128-bit division runtime,
syscall table generated from the fenrir kernel (gen_sysbits.sh).
Toolchain file cmake/toolchain-powerpc-e500.cmake (soft-float,
-msecure-plt, tests under qemu-ppc -cpu e500v2).

Generic code made word-size and byte-order neutral: ElfW() in the
dynamic linker, TLS layout per variant, unwinder split into
eh_unwind_core.h, 64-bit time_t/off_t/rlim_t on ILP32 with time64
syscalls, statx-based stat, mmap2/_llseek/pread64 pairs, shmctl/timex/
itimer/wait4 conversions, O_LARGEFILE, per-arch termios/ioctl/setjmp
headers.

Bugs fixed that only hid on x86_64: htons/htonl always swapped, printf
read long double as x87, ostream passed long to %lld, getdents64
record used long, bitset/inttypes assumed 64-bit long (PRIdFAST16/32
were wrong everywhere), CMAKE_ASM_FLAGS was clobbered.

powerpc: 154/154 e2e under qemu-ppc; x86_64 unchanged (154/155,
pre-existing __divti3 link failure of blogi_stdlib_gaps_test).

Co-Authored-By: default avatarClaude Opus 5.5 <noreply@anthropic.com>
parent 6f78256f
Loading
Loading
Loading
Loading
+1 −0
Changes for .gitignore: 1 added line, 0 removed lines.
Original line number Diff line number Diff line
build/*
build-*/
.vs/*
.out/*
out/*
+4 −0
Changes for 3rdparty/CMakeLists.txt: 4 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -22,4 +22,8 @@ set(INSTALL_CMAKE_DIR lib/cmake/yaml)
# The installed libyaml.a also gets linked into shared objects (real case:
# libconfplus's yaml.cfg.so backend), so it has to be position-independent.
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
# host-targeted (see above): nothing to build when cross-compiling, the
# target's libyaml is src/'s yaml_systempp
if(NOT CMAKE_CROSSCOMPILING)
    add_subdirectory(libyaml)
endif()
+54 −0
Changes for cmake/toolchain-powerpc-e500.cmake: 54 added lines, 0 removed lines.
Original line number Diff line number Diff line
# Cross-compiling systempp for 32-bit big-endian PowerPC e500v2 (Freescale/
# NXP QorIQ P1010/P1020/P2020, MPC85xx; e.g. the Inventronics NAS ITX).
#
#   cmake -G Ninja -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-powerpc-e500.cmake ..
#
# Float ABI: soft-float. e500v2 has no classic FPU, only SPE; LLVM's SPE
# backend (-mspe) is little used, OpenWrt and Debian ("powerpcspe" is
# gone) both settled on soft-float for these cores. -mcpu=e500 still
# matters: it makes LLVM emit msync instead of lwsync (illegal on e500v2)
# and allows isel. Set SYSTEMPP_PPC_FLOAT=spe to try hard-float SPE instead.
#
# -msecure-plt is required: lld only implements the secure PLT, whose
# position-independent call stubs load the target relative to r30 -- and
# clang only sets up r30 (the GOT pointer) in PIC/PIE code with it; without
# it every PLT call jumps through a stale r30.
#
# Tests run under qemu-user (qemu-ppc -cpu e500v2) when it is installed.
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR powerpc)

set(SYSTEMPP_TRIPLE powerpc-linux-gnu)
set(CMAKE_C_COMPILER clang)
set(CMAKE_CXX_COMPILER clang++)
set(CMAKE_ASM_COMPILER clang)
set(CMAKE_C_COMPILER_TARGET ${SYSTEMPP_TRIPLE})
set(CMAKE_CXX_COMPILER_TARGET ${SYSTEMPP_TRIPLE})
set(CMAKE_ASM_COMPILER_TARGET ${SYSTEMPP_TRIPLE})

if(NOT DEFINED SYSTEMPP_PPC_FLOAT)
    set(SYSTEMPP_PPC_FLOAT soft)
endif()
if(SYSTEMPP_PPC_FLOAT STREQUAL "spe")
    set(_ppc_flags "-mcpu=e500 -mspe -msecure-plt")
else()
    set(_ppc_flags "-mcpu=e500 -msoft-float -msecure-plt")
endif()
set(CMAKE_C_FLAGS_INIT "${_ppc_flags}")
set(CMAKE_CXX_FLAGS_INIT "${_ppc_flags}")
set(CMAKE_ASM_FLAGS_INIT "${_ppc_flags}")
set(CMAKE_EXE_LINKER_FLAGS_INIT "-fuse-ld=lld")
set(CMAKE_SHARED_LINKER_FLAGS_INIT "-fuse-ld=lld")
set(CMAKE_MODULE_LINKER_FLAGS_INIT "-fuse-ld=lld")

# no libc for the target yet: compiler checks must not try to link
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)

find_program(SYSTEMPP_QEMU_PPC qemu-ppc)
if(SYSTEMPP_QEMU_PPC)
    set(CMAKE_CROSSCOMPILING_EMULATOR ${SYSTEMPP_QEMU_PPC} -cpu e500v2)
endif()

set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
+10 −2
Changes for include/arpa/inet.h: 10 added lines, 2 removed lines.
Original line number Diff line number Diff line
@@ -44,10 +44,14 @@
/* static inline, not macros: the previous htons() was a textual macro,
 * which evaluates its argument multiple times (a real hazard for any
 * caller passing an expression with side effects, e.g. htons(port++)).
 * x86_64 is little-endian, so all four of these are real byte swaps,
 * not no-ops. */
 * Byte swaps on little-endian targets (x86_64), the identity on
 * big-endian ones (powerpc) -- network byte order is big endian. */
static inline unsigned short htons(unsigned short x) {
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
    return x;
#else
    return (unsigned short)((x << 8) | (x >> 8));
#endif
}

static inline unsigned short ntohs(unsigned short x) {
@@ -55,10 +59,14 @@ static inline unsigned short ntohs(unsigned short x) {
}

static inline unsigned int htonl(unsigned int x) {
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
    return x;
#else
    return ((x & 0x000000ffU) << 24) |
           ((x & 0x0000ff00U) << 8)  |
           ((x & 0x00ff0000U) >> 8)  |
           ((x & 0xff000000U) >> 24);
#endif
}

static inline unsigned int ntohl(unsigned int x) {
+15 −2
Changes for include/arpa/nameser.h: 15 added lines, 2 removed lines.
Original line number Diff line number Diff line
@@ -107,10 +107,22 @@
#define T_ANY     255
#define T_CAA     257

/* The fixed 12-byte message header. Bit-field order is the little-endian
 * one (x86_64), as in glibc. */
/* The fixed 12-byte message header. Bit-field order follows the byte
 * order (little endian: x86_64, big endian: powerpc), as in glibc. */
typedef struct {
    unsigned id : 16;       /* query identification number */
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
    unsigned qr : 1;        /* response flag */
    unsigned opcode : 4;    /* purpose of message */
    unsigned aa : 1;        /* authoritative answer */
    unsigned tc : 1;        /* truncated message */
    unsigned rd : 1;        /* recursion desired */
    unsigned ra : 1;        /* recursion available */
    unsigned unused : 1;
    unsigned ad : 1;        /* authentic data from named */
    unsigned cd : 1;        /* checking disabled by resolver */
    unsigned rcode : 4;     /* response code */
#else
    unsigned rd : 1;        /* recursion desired */
    unsigned tc : 1;        /* truncated message */
    unsigned aa : 1;        /* authoritative answer */
@@ -121,6 +133,7 @@ typedef struct {
    unsigned ad : 1;        /* authentic data from named */
    unsigned unused : 1;
    unsigned ra : 1;        /* recursion available */
#endif
    unsigned qdcount : 16;  /* number of question entries */
    unsigned ancount : 16;  /* number of answer entries */
    unsigned nscount : 16;  /* number of authority entries */
Loading