From e60b597af5cd2c7a61faaa018a39eec9ed8714d5 Mon Sep 17 00:00:00 2001 From: Christian Helmuth Date: Tue, 21 May 2019 17:13:24 +0200 Subject: [PATCH] linux: 32-bit compatibility with GCC versions before 7 GCC version 7 and above generate calls to __divmoddi for 64bit integer division on 32-bit. Unfortunately, libgcc liberaries of older compilers lack this symbol and are still in use by Debian/Ubuntu LTS at least. --- repos/base-linux/lib/mk/lx_hybrid.mk | 2 + repos/base-linux/src/lib/lx_hybrid/libgcc.c | 73 +++++++++++++++++++++ 2 files changed, 75 insertions(+) create mode 100644 repos/base-linux/src/lib/lx_hybrid/libgcc.c diff --git a/repos/base-linux/lib/mk/lx_hybrid.mk b/repos/base-linux/lib/mk/lx_hybrid.mk index 77686587b2..43f93b6ee1 100644 --- a/repos/base-linux/lib/mk/lx_hybrid.mk +++ b/repos/base-linux/lib/mk/lx_hybrid.mk @@ -1,8 +1,10 @@ SRC_CC += lx_hybrid.cc new_delete.cc capability_space.cc SRC_CC += signal_transmitter.cc signal.cc +SRC_C += libgcc.c vpath new_delete.cc $(BASE_DIR)/src/lib/cxx vpath lx_hybrid.cc $(REP_DIR)/src/lib/lx_hybrid +vpath libgcc.c $(REP_DIR)/src/lib/lx_hybrid # add parts of the base library that are shared with core LIBS += base-linux-common timeout diff --git a/repos/base-linux/src/lib/lx_hybrid/libgcc.c b/repos/base-linux/src/lib/lx_hybrid/libgcc.c new file mode 100644 index 0000000000..d3fd12093a --- /dev/null +++ b/repos/base-linux/src/lib/lx_hybrid/libgcc.c @@ -0,0 +1,73 @@ +/* + * \brief libgcc contrib code for lx-hybrid components + * \author Christian Helmuth + * \date 2019-05-21 + * + * GCC version 7 and above generate calls to __divmoddi for 64bit integer + * division on 32-bit. Unfortunately, libgcc liberaries of older compilers + * lack this symbol and are still in use by Debian/Ubuntu LTS at least. + * + * Implementation is similar to GCC 8.3 libgcc/libgcc2.c and libgcc/libgcc2.h - + * original license header follows. + */ +/* Copyright (C) 1989-2016 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +Under Section 7 of GPL version 3, you are granted additional +permissions described in the GCC Runtime Library Exception, version +3.1, as published by the Free Software Foundation. + +You should have received a copy of the GNU General Public License and +a copy of the GCC Runtime Library Exception along with this program; +see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +. */ + +#ifdef __i386__ +typedef int SItype __attribute__ ((mode (SI))); +typedef int DItype __attribute__ ((mode (DI))); +typedef unsigned int UDItype __attribute__ ((mode (DI))); +typedef SItype Wtype; +typedef DItype DWtype; +typedef UDItype UDWtype; +struct DWstruct { Wtype low, high; }; +typedef union { struct DWstruct s; DWtype ll; } DWunion; + +extern UDWtype __udivmoddi4 (UDWtype, UDWtype, UDWtype *); + +DWtype __divmoddi4 (DWtype u, DWtype v, DWtype *rp) +{ + Wtype c1 = 0, c2 = 0; + DWunion uu = {.ll = u}; + DWunion vv = {.ll = v}; + DWtype w; + DWtype r; + + if (uu.s.high < 0) + c1 = ~c1, c2 = ~c2, + uu.ll = -uu.ll; + if (vv.s.high < 0) + c1 = ~c1, + vv.ll = -vv.ll; + + w = __udivmoddi4 (uu.ll, vv.ll, (UDWtype*)&r); + if (c1) + w = -w; + if (c2) + r = -r; + + *rp = r; + return w; +} +#endif +