Sisyphus repositório
Última atualização: 1 outubro 2023 | SRPMs: 18631 | Visitas: 37766933
en ru br
ALT Linux repositórios
S:2.4-alt2
5.0: 1.10-alt1
4.1: 1.10-alt1
4.0: 1.10-alt1
3.0: 1.10-alt1

Group :: Sistema/Bibliotecas
RPM: libffcall

 Main   Changelog   Spec   Patches   Sources   Download   Gear   Bugs e FR  Repocop 

Patch: libffcall-2.4-e2k.patch
Download


From 6c8a45113b96867a45881b4c70b3c1611ce58b37 Mon Sep 17 00:00:00 2001
From: Ilya Kurdyukov <jpegqs@gmail.com>
Date: Tue, 28 Dec 2021 18:06:12 +0700
Subject: [PATCH] libffcall-2.4 e2k support
LCC >= 1.25.18 or LCC >= 1.26.04 is required
for __clear_cache() to work properly
---
 avcall/Makefile.in                 |  3 ++
 avcall/avcall-e2k.c                | 79 +++++++++++++++++++++++++++++
 avcall/avcall-internal.h           | 37 ++++++++++++++
 callback/trampoline_r/test1.c      |  3 ++
 callback/trampoline_r/trampoline.c | 40 ++++++++++++++-
 callback/vacall_r/Makefile.in      |  3 ++
 trampoline/trampoline.c            | 43 +++++++++++++++-
 vacall/Makefile.in                 |  3 ++
 vacall/vacall-e2k.c                | 81 ++++++++++++++++++++++++++++++
 vacall/vacall-internal.h           | 29 +++++++++++
 10 files changed, 319 insertions(+), 2 deletions(-)
 create mode 100644 avcall/avcall-e2k.c
 create mode 100644 vacall/vacall-e2k.c
diff --git a/avcall/Makefile.in b/avcall/Makefile.in
index 466023d..0a646ee 100644
--- a/avcall/Makefile.in
+++ b/avcall/Makefile.in
@@ -164,6 +164,9 @@ avcall-arm64.s : $(srcdir)/avcall-arm64-macro.S $(srcdir)/avcall-arm64-macos-mac
 	esac; \
 	$(CPP) $(ASPFLAGS) -I$(srcdir)/../common $(srcdir)/$${input} | grep -v '^ *#line' | grep -v '^#' | sed -e 's,% ,%,g' -e 's,//,@,g' -e 's,\$$,#,g' > avcall-arm64.s
 
+avcall-e2k.lo : $(srcdir)/avcall-e2k.c
+	$(LIBTOOL_COMPILE) $(CC) -I$(srcdir)/.. $(CPPFLAGS) $(CFLAGS) -c $(srcdir)/avcall-e2k.c -o avcall-e2k.lo
+
 avcall-powerpc.lo : avcall-powerpc.s
 	$(LIBTOOL_COMPILE) $(CC) @GCC_X_NONE@ -c avcall-powerpc.s
 
diff --git a/avcall/avcall-e2k.c b/avcall/avcall-e2k.c
new file mode 100644
index 0000000..a59c98b
--- /dev/null
+++ b/avcall/avcall-e2k.c
@@ -0,0 +1,79 @@
+/**
+  Copyright 2021 Ilya Kurdyukov <jpegqs@gmail.com> for BaseALT, Ltd
+
+  This program 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 2 of the License, or
+  (at your option) any later version.
+
+  This program 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.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+**/
+/*----------------------------------------------------------------------
+  Foreign function interface for Elbrus 2000 with LCC compiler.
+
+  This calls a C function with an argument list built up using macros
+  defined in avcall.h.
+  ----------------------------------------------------------------------*/
+#include "avcall-internal.h"
+#include <string.h>
+
+#define RETURN(TYPE)  (*(TYPE*)l->raddr = (TYPE)ret.r[0]); break;
+
+typedef struct { __avword r[8]; } regs_t;
+
+#define STACK_EXTRA 8
+
+int
+avcall_call(av_alist* list)
+{
+  regs_t ret;
+  __av_alist* l = &AV_LIST_INNER(list);
+  /* make room for argument list */
+  __avword* argframe = __builtin_alloca((__AV_ALIST_WORDS - STACK_EXTRA) * sizeof(__avword));
+  int arglen = l->aptr - l->args;
+  __avword i;
+
+  /* skip the extra space generated by the compiler  */
+  argframe -= STACK_EXTRA;
+
+  /* push function args onto stack */
+  for (i = 0; i < arglen; i++) argframe[i] = l->args[i];
+
+  /* call function */
+  ret = (*(regs_t(*)(regs_t))l->func)(*(regs_t*)argframe);
+
+  switch (l->rtype) {
+    case __AVvoid:
+      break;
+    case __AVchar:
+    case __AVschar:
+    case __AVuchar:
+      RETURN(char)
+    case __AVshort:
+    case __AVushort:
+      RETURN(short)
+    case __AVint:
+    case __AVuint:
+    case __AVfloat:
+      RETURN(int)
+    case __AVlong:
+    case __AVulong:
+    case __AVlonglong:
+    case __AVulonglong:
+    case __AVdouble:
+      RETURN(long)
+    case __AVvoidp:
+      RETURN(void*)
+    case __AVstruct:
+      if (l->rsize <= sizeof(ret)) *(regs_t*)argframe = ret;
+      memcpy(l->raddr, argframe, l->rsize);
+      break;
+  }
+  return 0;
+}
diff --git a/avcall/avcall-internal.h b/avcall/avcall-internal.h
index c878134..f36cb1f 100644
--- a/avcall/avcall-internal.h
+++ b/avcall/avcall-internal.h
@@ -1555,4 +1555,41 @@ extern void avcall_structcpy (void* dest, const void* src, unsigned long size, u
 #endif
 
 
+#if defined(__e2k__)
+#define __av_start1(LIST,LIST_ARGS_END)					\
+   (LIST).aptr = &(LIST).args[0],
+
+#define __av_word(LIST,VAL)						\
+  ((LIST).aptr >= (LIST).eptr ? -1 :					\
+   (*(LIST).aptr = (__avword)(VAL), (LIST).aptr++, 0))
+
+#define _av_double(LIST,VAL)						\
+  ((LIST).aptr >= (LIST).eptr ? -1 :					\
+   (*(double*)(LIST).aptr = (double)(VAL), (LIST).aptr++, 0))
+
+#define _av_float(LIST,VAL)						\
+  ((LIST).aptr >= (LIST).eptr ? -1 :					\
+   (*(float*)(LIST).aptr = (float)(VAL),				\
+    ((float*)(LIST).aptr)[1] = 0, (LIST).aptr++, 0))
+
+#define __av_longlong		__av_long
+#define __av_ulonglong		__av_ulong
+
+#undef __av_start_struct2
+#define __av_start_struct2(LIST,TYPE_SIZE,TYPE_SPLITTABLE)  0
+
+#define __av_struct(LIST,TYPE_SIZE,TYPE_ALIGN,VAL)			\
+  ((TYPE_SIZE) <= sizeof(__avword)					\
+   ? ((LIST).aptr >= (LIST).eptr ? -1 :					\
+      (__av_struct_copy(TYPE_SIZE,TYPE_ALIGN,(void*)(LIST).aptr,VAL),	\
+      (LIST).aptr++, 0))						\
+   : ((__avword*)((((uintptr_t)(LIST).aptr+2*sizeof(__avword)-1) & -2*sizeof(__avword))+(TYPE_SIZE)) > (LIST).eptr \
+      ? -1 :								\
+      ((LIST).aptr = (__avword*)(((uintptr_t)(LIST).aptr+2*sizeof(__avword)-1) & -2*sizeof(__avword)), \
+       __av_struct_copy(TYPE_SIZE,TYPE_ALIGN,(void*)(LIST).aptr,VAL),	\
+       (LIST).aptr = (__avword*)(((uintptr_t)(LIST).aptr+(TYPE_SIZE)+sizeof(__avword)-1) & -sizeof(__avword)), \
+       0)))
+#endif /* __e2k__ */
+
+
 #endif /* _AVCALL_INTERNAL_H */
diff --git a/callback/trampoline_r/test1.c b/callback/trampoline_r/test1.c
index 4b2f9f8..c5feb27 100644
--- a/callback/trampoline_r/test1.c
+++ b/callback/trampoline_r/test1.c
@@ -81,6 +81,9 @@ register void* env __asm__("r10");
 #if defined(__s390__) || defined(__s390x__)
 register void* env __asm__("r0");
 #endif
+#ifdef __e2k__
+register void* env __asm__("g16");
+#endif
 #if defined(__riscv32__) || defined(__riscv64__)
 register void* env __asm__("t2");
 #endif
diff --git a/callback/trampoline_r/trampoline.c b/callback/trampoline_r/trampoline.c
index 5d4f8c2..0579369 100644
--- a/callback/trampoline_r/trampoline.c
+++ b/callback/trampoline_r/trampoline.c
@@ -326,6 +326,17 @@ static int open_noinherit (const char *filename, int flags, int mode)
 #define TRAMP_LENGTH 32
 #define TRAMP_ALIGN 8
 #endif
+#ifdef __e2k__
+#define TRAMP_LENGTH 48
+#define TRAMP_ALIGN 64
+#ifdef EXECUTABLE_VIA_MALLOC_THEN_MPROTECT
+#undef EXECUTABLE_VIA_MALLOC_THEN_MPROTECT
+#define EXECUTABLE_VIA_MMAP
+#endif
+#ifndef MAP_VARIABLE
+#define MAP_VARIABLE 0
+#endif
+#endif
 
 #ifndef TRAMP_BIAS
 #define TRAMP_BIAS 0
@@ -1257,6 +1268,33 @@ __TR_function alloc_trampoline_r (__TR_function address, void* data0, void* data
   (*(unsigned long *) (function +24))
 #define tramp_data(function)  \
   (*(unsigned long *) (function +16))
+#endif
+#if defined(__e2k__)
+#define swaphilo(x) ((x) << 32 | (x) >> 32)
+  /* function:
+   *    nop 7
+   *    movtd,sm <address>, %ctpr1; ipd 2
+   *    addd 0, <data>, %g16
+   *
+   *    nop
+   *
+   *    ct %ctpr1
+   */
+  *(long *)  (function + 0) = 0x800000000C0013B3L;
+  *(long *)  (function + 8) = 0x11C0DCF0E1C0DED1L;
+  *(long *)  (function +16) = swaphilo((unsigned long) address);
+  *(long *)  (function +24) = swaphilo((unsigned long) data);
+  *(long *)  (function +32) = 0;
+  *(long *)  (function +40) = 0xC000042000001001L;
+#define is_tramp(function)  \
+  *(unsigned long *) (function + 0) == 0x800000000C0013B3L && \
+  *(unsigned long *) (function + 8) == 0x11C0DCF0E1C0DED1L && \
+  *(unsigned long *) (function +32) == 0 && \
+  *(unsigned long *) (function +40) == 0xC000042000001001L
+#define tramp_address(function)  \
+  swaphilo(*(unsigned long *) (function +16))
+#define tramp_data(function)  \
+  swaphilo(*(unsigned long *) (function +24))
 #endif
   /*
    * data:
@@ -1382,7 +1420,7 @@ __TR_function alloc_trampoline_r (__TR_function address, void* data0, void* data
   /* This assumes that the trampoline fits in at most two cache lines. */
   __TR_clear_cache(function_x,function_x+TRAMP_CODE_LENGTH-1);
 #endif
-#if defined(__arm__) || defined(__armhf__) || defined(__arm64__)
+#if defined(__arm__) || defined(__armhf__) || defined(__arm64__) || defined(__e2k__)
   /* On ARM, cache flushing can only be done through a system call.
      GCC implements it for Linux with EABI, through an "swi 0" with code
      0xf0002. For other systems, it may be an "swi 0x9f0002",
diff --git a/callback/vacall_r/Makefile.in b/callback/vacall_r/Makefile.in
index 012f4d9..2223704 100644
--- a/callback/vacall_r/Makefile.in
+++ b/callback/vacall_r/Makefile.in
@@ -148,6 +148,9 @@ vacall-arm64.s : $(srcdir)/vacall-arm64-macro.S $(srcdir)/vacall-arm64-macos-mac
 	esac; \
 	$(CPP) $(ASPFLAGS) -I$(srcdir) -I$(srcdir)/../../common $(srcdir)/$${input} | grep -v '^ *#line' | grep -v '^#' | sed -e 's,% ,%,g' -e 's,//,@,g' -e 's,\$$,#,g' > vacall-arm64.s
 
+vacall-e2k.lo : $(srcdir)/../../vacall/vacall-e2k.c
+	$(LIBTOOL_COMPILE) $(CC) $(INCLUDES) -I$(srcdir)/../.. $(CPPFLAGS) $(CFLAGS) -DREENTRANT -c $(srcdir)/../../vacall/vacall-e2k.c -o vacall-e2k.lo
+
 vacall-powerpc.lo : vacall-powerpc.s
 	$(LIBTOOL_COMPILE) $(CC) @GCC_X_NONE@ -c vacall-powerpc.s
 
diff --git a/trampoline/trampoline.c b/trampoline/trampoline.c
index 9b79e0d..a82dab3 100644
--- a/trampoline/trampoline.c
+++ b/trampoline/trampoline.c
@@ -330,6 +330,17 @@ static int open_noinherit (const char *filename, int flags, int mode)
 #define TRAMP_LENGTH 48
 #define TRAMP_ALIGN 8
 #endif
+#ifdef __e2k__
+#define TRAMP_LENGTH 56
+#define TRAMP_ALIGN 64
+#ifdef EXECUTABLE_VIA_MALLOC_THEN_MPROTECT
+#undef EXECUTABLE_VIA_MALLOC_THEN_MPROTECT
+#define EXECUTABLE_VIA_MMAP
+#endif
+#ifndef MAP_VARIABLE
+#define MAP_VARIABLE 0
+#endif
+#endif
 
 #ifndef TRAMP_BIAS
 #define TRAMP_BIAS 0
@@ -1514,6 +1525,36 @@ trampoline_function_t alloc_trampoline (trampoline_function_t address, void** va
 #define tramp_data(function)  \
   (*(unsigned long *) (function +24))
 #endif
+#if defined(__e2k__)
+#define swaphilo(x) ((x) << 32 | (x) >> 32)
+  /* function:
+   *    movtd,sm <address>, %ctpr1; ipd 2
+   *    addd 0, <data>, %g16
+   *
+   *    nop 7
+   *    std 0, <variable>, %g16
+   *
+   *    ct %ctpr1
+   */
+  *(long *)  (function + 0) = 0x800000000C001033L;
+  *(long *)  (function + 8) = 0x11C0DCF0E1C0DED1L;
+  *(long *)  (function +16) = swaphilo((unsigned long) address);
+  *(long *)  (function +24) = swaphilo((unsigned long) data);
+  *(long *)  (function +32) = 0x27C0DCF010000391L;
+  *(long *)  (function +40) = swaphilo((unsigned long) variable);
+  *(long *)  (function +48) = 0xC000042000001001L;
+#define is_tramp(function)  \
+  *(unsigned long *) (function + 0) == 0x800000000C001033L && \
+  *(unsigned long *) (function + 8) == 0x11C0DCF0E1C0DED1L && \
+  *(unsigned long *) (function +32) == 0x27C0DCF010000391L && \
+  *(unsigned long *) (function +48) == 0xC000042000001001L
+#define tramp_address(function)  \
+  swaphilo(*(unsigned long *) (function +16))
+#define tramp_variable(function)  \
+  swaphilo(*(unsigned long *) (function +40))
+#define tramp_data(function)  \
+  swaphilo(*(unsigned long *) (function +24))
+#endif
 
   /* 3. Set memory protection to "executable" */
 
@@ -1631,7 +1672,7 @@ trampoline_function_t alloc_trampoline (trampoline_function_t address, void** va
   /* This assumes that the trampoline fits in at most two cache lines. */
   __TR_clear_cache(function_x,function_x+TRAMP_CODE_LENGTH-1);
 #endif
-#if defined(__arm__) || defined(__armhf__) || defined(__arm64__)
+#if defined(__arm__) || defined(__armhf__) || defined(__arm64__) || defined(__e2k__)
   /* On ARM, cache flushing can only be done through a system call.
      GCC implements it for Linux with EABI, through an "swi 0" with code
      0xf0002. For other systems, it may be an "swi 0x9f0002",
diff --git a/vacall/Makefile.in b/vacall/Makefile.in
index ec31846..98b021a 100644
--- a/vacall/Makefile.in
+++ b/vacall/Makefile.in
@@ -144,6 +144,9 @@ vacall-arm64.s : $(srcdir)/vacall-arm64-macro.S $(srcdir)/vacall-arm64-macos-mac
 	esac; \
 	$(CPP) $(ASPFLAGS) -I$(srcdir)/../common $(srcdir)/$${input} | grep -v '^ *#line' | grep -v '^#' | sed -e 's,% ,%,g' -e 's,//,@,g' -e 's,\$$,#,g' > vacall-arm64.s
 
+vacall-e2k.@OBJEXT@ : $(srcdir)/vacall-e2k.c
+	$(CC) $(INCLUDES) -I$(srcdir)/.. $(CPPFLAGS) $(CFLAGS) -c $(srcdir)/vacall-e2k.c -o vacall-e2k.@OBJEXT@
+
 vacall-powerpc.@OBJEXT@ : vacall-powerpc.s
 	$(CC) @GCC_X_NONE@ -c vacall-powerpc.s
 
diff --git a/vacall/vacall-e2k.c b/vacall/vacall-e2k.c
new file mode 100644
index 0000000..792de68
--- /dev/null
+++ b/vacall/vacall-e2k.c
@@ -0,0 +1,81 @@
+/* vacall function for e2k CPU */
+
+/*
+  Copyright 2021 Ilya Kurdyukov <jpegqs@gmail.com> for BaseALT, Ltd
+ *
+ * This program 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "vacall-internal.h"
+#include <string.h>
+
+#ifdef REENTRANT
+#define vacall_receiver callback_receiver
+typedef struct { void (*vacall_function) (void*,va_alist); void* arg; } env_t;
+register env_t* env __asm__("g16");
+#endif
+
+typedef struct { __vaword r[__VA_IARG_NUM]; } regs_t;
+
+#ifdef REENTRANT
+static
+#endif
+regs_t /* the return type is variable */
+vacall_receiver (regs_t iarg, regs_t sarg)
+{
+  __va_alist list;
+  regs_t *ret = (regs_t*)list.iarg;
+  /* Must be saved early to prevent the compiler
+     from saving "iarg" in the caller's stack frame. */
+  *ret = iarg;
+
+  /* Prepare the va_alist. */
+  list.flags = 0;
+  list.aptr = (long)(&sarg - 1);
+  list.sptr = (long)&sarg;
+  list.raddr = (void*)0;
+  list.rtype = __VAvoid;
+  /* Call vacall_function. The macros do all the rest. */
+#ifndef REENTRANT
+  (*vacall_function) (&list);
+#else /* REENTRANT */
+  (*env->vacall_function) (env->arg, &list);
+#endif
+
+  /* Put return value into proper register. */
+  switch (list.rtype) {
+    case __VAvoid: break;
+#define RET2(x, y) case __VA##x: ret->r[0] = (long)list.tmp._##y; break;
+#define RET(x) RET2(x, x)
+    RET(char) RET(schar) RET(uchar)
+    RET(short) RET(ushort)
+    RET(int) RET(uint)
+    RET(long) RET(ulong)
+    RET(longlong) RET(ulonglong)
+    RET2(float, uint)
+    RET2(double, ulong)
+    RET2(voidp, ptr)
+    case __VAstruct:
+      memcpy(list.rsize > sizeof(*ret) ? &sarg - 1 : ret, list.raddr, list.rsize);
+  }
+  return *ret;
+}
+
+#ifdef REENTRANT
+__vacall_r_t
+callback_get_receiver (void)
+{
+  return (__vacall_r_t)(void*)&callback_receiver;
+}
+#endif
diff --git a/vacall/vacall-internal.h b/vacall/vacall-internal.h
index c196348..09214ef 100644
--- a/vacall/vacall-internal.h
+++ b/vacall/vacall-internal.h
@@ -225,6 +225,11 @@ typedef struct vacall_alist
   float          farg[__VA_FARG_NUM];
   double         darg[__VA_FARG_NUM];
 #endif
+#if defined(__e2k__)
+#define __VA_IARG_NUM 8
+  __vaword       iarg[__VA_IARG_NUM];
+  uintptr_t      sptr;
+#endif
 } __va_alist;
 
 
@@ -1210,4 +1215,28 @@ typedef struct vacall_alist
 extern void vacall_structcpy (void* dest, const void* src, unsigned long size, unsigned long alignment);
 
 
+#ifdef __e2k__
+#define __va_align_double(LIST)
+#define _va_arg_longlong	_va_arg_long
+#define _va_arg_ulonglong	_va_arg_ulong
+
+#define __va_arg_adjusted(LIST,TYPE_SIZE,TYPE_ALIGN)  \
+  ((LIST)->aptr += __va_argsize(TYPE_SIZE),				\
+   (LIST)->aptr > (LIST)->sptr						\
+    ? (void*)((LIST)->aptr - __va_argsize(TYPE_SIZE))			\
+    : (void*)((uintptr_t)&(LIST)->iarg[__VA_IARG_NUM] + (LIST)->aptr - __va_argsize(TYPE_SIZE) - (LIST)->sptr) \
+  )
+#define __va_arg_struct(LIST,TYPE_SIZE,TYPE_ALIGN)  \
+  (__va_align_struct(LIST,TYPE_SIZE,((TYPE_SIZE) > sizeof(__vaword) ? 2*sizeof(__vaword) : sizeof(__vaword)))		\
+   __va_arg_adjusted(LIST,TYPE_SIZE,TYPE_ALIGN)				\
+  )
+
+#undef __va_start_struct
+#define __va_start_struct(LIST,TYPE_SIZE,TYPE_ALIGN,TYPE_SPLITTABLE,FLAGS)  \
+  (__va_start(LIST,__VAstruct,FLAGS),					\
+   (LIST)->rsize = (TYPE_SIZE),						\
+   (LIST)->raddr = (TYPE_SIZE) > sizeof((LIST)->iarg) ? (void*)((LIST)->sptr - sizeof((LIST)->iarg)) : (void*)(LIST)->iarg \
+  )
+#endif /* __e2k__ */
+
 #endif /* _VACALL_INTERNAL_H */
-- 
2.17.1
 
projeto & código: Vladimir Lettiev aka crux © 2004-2005, Andrew Avramenko aka liks © 2007-2008
mantenedor atual: Michael Shigorin
mantenedor da tradução: Fernando Martini aka fmartini © 2009