]> Savannah Git Hosting - gnulib.git/commitdiff
jit/cache: Fix for arm CPUs with GCC target arm-linux-gnueabihf.
authorBruno Haible <bruno@clisp.org>
Wed, 10 Jan 2024 14:26:53 +0000 (15:26 +0100)
committerBruno Haible <bruno@clisp.org>
Thu, 18 Jan 2024 08:29:26 +0000 (09:29 +0100)
* tests/jit/test-cache.c (CODE): Define differently on arm.
(SET_CODE, IS, SET_IS): New macros.
(main): New variables is_of_return1, is_of_return2. Use the SET_CODE and
SET_IS macros.

ChangeLog
tests/jit/test-cache.c

index aa6177fbd35bdfe6fd677363e8df6cb5c9c7902e..b6de485579491dd5a7e739857192f15670531024 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2024-01-10  Bruno Haible  <bruno@clisp.org>
+
+       jit/cache: Fix for arm CPUs with GCC target arm-linux-gnueabihf.
+       * tests/jit/test-cache.c (CODE): Define differently on arm.
+       (SET_CODE, IS, SET_IS): New macros.
+       (main): New variables is_of_return1, is_of_return2. Use the SET_CODE and
+       SET_IS macros.
+
 2024-01-10  Bruno Haible  <bruno@clisp.org>
 
        jit/cache tests: Avoid compiler warnings on OpenBSD.
index cabbc0ddfdeb057c8dc6e5bb830d493c3226f052..cad6d2a214447e691b23c0d9019d1b614d182914 100644 (file)
@@ -90,7 +90,25 @@ struct func
 #ifdef FUNCPTR_POINTS_TO_CODE
 /* A function pointer points directly to the code.  */
 # define COPY_FUNCPTR(funcptr) funcptr
-# define CODE(funcptr) (funcptr)
+/* On arm, bit 0 of a function pointer tells which instruction set the function
+   uses.  */
+# if defined __arm__ || defined __armhf__
+#  define CODE(funcptr) ((void *) ((uintptr_t) (funcptr) & ~(intptr_t)1))
+#  define SET_CODE(funcptr,code_addr) \
+     ((void) ((funcptr) =                                     \
+              (void *) (((uintptr_t) (funcptr) & (intptr_t)1) \
+                        | (uintptr_t) (code_addr))))
+#  define IS(funcptr)  ((uintptr_t) (funcptr) & 1)
+#  define SET_IS(funcptr,is)  \
+     ((void) ((funcptr) = \
+              (void *) (((uintptr_t) (funcptr) & ~(intptr_t)1) | (is))))
+# else
+#  define CODE(funcptr) (funcptr)
+#  define SET_CODE(funcptr,code_addr) \
+     ((void) ((funcptr) = (void *) (code_addr)))
+#  define IS(funcptr) ((void) (funcptr), 0)
+#  define SET_IS(funcptr,is) ((void) (funcptr), (void) (is))
+# endif
 #else
 /* A function pointer points to a 'struct func'.  */
 # if FUNCPTR_BIAS
@@ -119,6 +137,10 @@ xcopy_structptr (struct func *structptr)
     structptr_to_funcptr (xcopy_structptr (funcptr_to_structptr (funcptr)))
 # define CODE(funcptr) \
     ((funcptr_to_structptr (funcptr))->code_address)
+# define SET_CODE(funcptr,code_addr) \
+    ((void) (CODE (funcptr) = (code_addr)))
+# define IS(funcptr) ((void) (funcptr), 0)
+# define SET_IS(funcptr,is) ((void) (funcptr), (void) (is))
 #endif
 
 /* This test assumes that the code generated by the compiler for the
@@ -212,6 +234,8 @@ main ()
   void const *code_of_return2;
   size_t size_of_return1;
   size_t size_of_return2;
+  int is_of_return1;
+  int is_of_return2;
 #if defined __OpenBSD__ || defined _RET_PROTECTOR
   /* OpenBSD maps code with PROT_EXEC (as opposed to PROT_READ | PROT_EXEC).
      We need to use predetermined code for 'return1' and 'return2'.  */
@@ -224,12 +248,17 @@ main ()
   code_of_return2 = return2_code;
   size_of_return1 = sizeof (return1_code);
   size_of_return2 = sizeof (return2_code);
+  /* On arm, return1_code and return2_code use the "ARM" instruction set.  */
+  is_of_return1 = 0;
+  is_of_return2 = 0;
 #else
   code_of_return1 = CODE (return1);
   code_of_return2 = CODE (return2);
   /* We assume that the code is not longer than 64 bytes.  */
   size_of_return1 = 64;
   size_of_return2 = 64;
+  is_of_return1 = IS (return1);
+  is_of_return2 = IS (return2);
 #endif
 
   int const pagesize = getpagesize ();
@@ -306,13 +335,15 @@ main ()
   }
 
   int (*f) (void) = COPY_FUNCPTR (return1);
-  CODE (f) = start;
+  SET_CODE (f, start);
 
   memcpy (start_rw, code_of_return1, size_of_return1);
+  SET_IS (f, is_of_return1);
   clear_cache (start, end);
   ASSERT (f () == 1);
 
   memcpy (start_rw, code_of_return2, size_of_return2);
+  SET_IS (f, is_of_return2);
   clear_cache (start, end);
   ASSERT (f () == 2);