Description: Fix for arm32
 Fix for arm32. add handle2, fix exec_function_i in eval.c
 use struct rusage, time_T clock in unixcall.c
 .
 euslisp (9.32-1) unstable; urgency=low
 .
Author: Kei Okada <kei.okada@gmail.com>

---
Origin: other
Reviewed-By: Kei Okada <kei.okada@gmail.com>
Last-Update: 2025-09-30

diff --git a/lisp/Makefile.LinuxARM b/lisp/Makefile.LinuxARM
index 780754d3..30f43633 100644
--- a/lisp/Makefile.LinuxARM
+++ b/lisp/Makefile.LinuxARM
@@ -106,7 +106,7 @@ THREADDEP=mthread_posix.c
 #THREADDEP=pthreads.c
 
 # If you don't like optimization, comment out the next line.
-OFLAGS=-O2
+OFLAGS=-O2 -fno-omit-frame-pointer
 
 # link-editor's default flags ?-rdynamic
 SOFLAGS:= $(LDFLAGS) -shared -Xlinker -build-id
diff --git a/lisp/c/eus.c b/lisp/c/eus.c
index 06f40da2..78bb5fb6 100644
--- a/lisp/c/eus.c
+++ b/lisp/c/eus.c
@@ -776,11 +776,15 @@ static void initclasses()
 /* 16    ---new for Solaris */
   LDMODULE=basicclass("LOAD-MODULE",C_CODE, &ldmodulecp,
 #if ARM // ARM uses entry2 in struct ldmodule in eus.h
-		      4,"ENTRY2",
+		      5,"ENTRY2",
 #else
 		      3,
 #endif
-		      "SYMBOL-TABLE","OBJECT-FILE", "HANDLE");
+		      "SYMBOL-TABLE","OBJECT-FILE", "HANDLE"
+#if ARM
+		      ,"HANDLE2"
+#endif
+		      );
   C_LDMOD=speval(LDMODULE);
 /*17*/
   LABREF=basicclass("LABEL-REFERENCE",C_OBJECT,&labrefcp,4,
@@ -971,7 +975,15 @@ static void initfeatures()
   /*system function module*/
   sysmod=makemodule(ctx,0);
   sysmod->c.ldmod.codevec=makeint(0);
-  sysmod->c.ldmod.handle=makeint((eusinteger_t)dlopen(0, RTLD_LAZY)>>2);
+  void *handle = dlopen(0, RTLD_LAZY);
+  sysmod->c.ldmod.handle=makeint((eusinteger_t)handle>>2);
+#if ARM
+#if (WORD_SIZE == 64)
+  sysmod->c.ldmod.handle2=makeint((eusinteger_t)handle&0x00000000ffffffff);
+#else
+  sysmod->c.ldmod.handle2=makeint((eusinteger_t)handle&0x0000ffff);
+#endif
+#endif
   sysobj=cons(ctx,sysmod, sysobj);
   }
 
diff --git a/lisp/c/eus.h b/lisp/c/eus.h
index 1019f458..60fc70ab 100644
--- a/lisp/c/eus.h
+++ b/lisp/c/eus.h
@@ -256,7 +256,11 @@ struct ldmodule {	/*foreign language object module*/
 #endif
     pointer symtab;
     pointer objname;
-    pointer handle;};	/* dl's handle */
+    pointer handle;
+#if ARM
+    pointer handle2;     /* some archtecture did not set code on 4 byte alignment */
+#endif
+    };
 
 struct closure {
     pointer codevec;
diff --git a/lisp/c/eval.c b/lisp/c/eval.c
index 94cb3d66..987b16fa 100644
--- a/lisp/c/eval.c
+++ b/lisp/c/eval.c
@@ -1003,7 +1003,7 @@ extern int exec_function_f(void (*)(), int *, int *, int, int *);
 	 "ldr	r3, [r7, #60]\n\t"	/* i 			*/	\
 	 /* https://community.arm.com/developer/ip-products/processors/b/processors-ip-blog/posts/function-parameters-on-32-bit-arm */ \
 	 "lsl	r4, r3, #2\n\t"		/* r4 = i * 2		*/	\
-	 "ldr	r1, [r7, #80]\n\t"	/* vargv[0]		*/	\
+	 "ldr	r1, [r7, #16]\n\t"	/* vargv[0]		*/	\
 	 "add	r1, r1, r4\n\t"		/* vargv[i]		*/	\
 	 "add	r2, sp, r4\n\t"		/* stack[i]		*/	\
 	 "ldr	r0, [r1]\n\t"						\
@@ -1050,19 +1050,21 @@ __asm__ (".align 4\n"
 	 ".global exec_function_i\n\t"
 	 ".type	exec_function_i, %function\n"
 	 "exec_function_i:\n\t"
-	 "push	{r7, lr}\n\t"
+	 "push	{r3, r4, r5, r6, r7, lr}\n\t"
 	 "sub	sp, sp, #136\n\t"
 	 "add	r7, sp, #64\n\t"
 	 "str	r0, [r7, #12]\n\t"	// fc
 	 "str	r1, [r7, #8]\n\t"	// iargv
 	 "str	r2, [r7, #4]\n\t"	// fargv
 	 "str	r3, [r7]\n\t"		// vcntr
+	 "ldr	r0, [r7, #96]\n\t"	// get 5th argument (vargv)
+	 "str	r0, [r7, #16]\n\t"	// store vargv to #16
 	 exec_function_asm("FUNCI")
 	 // retval
 	 "adds	r7, r7, #72\n\t"
 	 "mov	sp, r7\n\t"
 	 "@ sp needed	@\n\t"
-	  "pop	{r7, pc}\n\t"
+	  "pop	{r3, r4, r5, r6, r7, pc}\n\t"
 	 ".size	exec_function_i, .-exec_function_i\n\t"
 	 );
 
@@ -1070,13 +1072,15 @@ __asm__ (".align 4\n"
 	 ".global exec_function_f\n\t"
 	 ".type	exec_function_f, %function\n"
 	 "exec_function_f:\n\t"
-	 "push	{r7, lr}\n\t"
+	 "push	{r3, r4, r5, r6, r7, lr}\n\t"
 	 "sub	sp, sp, #136\n\t"
 	 "add	r7, sp, #64\n\t"
 	 "str	r0, [r7, #12]\n\t"	// fc
 	 "str	r1, [r7, #8]\n\t"	// iargv
 	 "str	r2, [r7, #4]\n\t"	// fargv
 	 "str	r3, [r7]\n\t"		// vcntr
+	 "ldr	r0, [r7, #96]\n\t"	// get 5th argument (vargv)
+	 "str	r0, [r7, #16]\n\t"	// store vargv to #16
 	 exec_function_asm("FUNCF")
 	 // retval
 	 "vmov	r0, s0	@ <retval>\n\t"
@@ -1084,7 +1088,7 @@ __asm__ (".align 4\n"
 	 "adds	r7, r7, #72\n\t"
 	 "mov	sp, r7\n\t"
 	 "@ sp needed	@\n\t"
-	  "pop	{r7, pc}\n\t"
+	  "pop	{r3, r4, r5, r6, r7, pc}\n\t"
 	 ".size	exec_function_f, .-exec_function_f\n\t"
 	 );
 
@@ -1119,8 +1123,13 @@ pointer args[];
   double f;
 
   if (code->c.fcode.entry2 != NIL) {
+#if (WORD_SIZE == 64)
     ifunc = (eusinteger_t (*)())((((eusinteger_t)ifunc)&0xffffffff00000000)
       | (intval(code->c.fcode.entry2)&0x00000000ffffffff));
+#else
+    ifunc = (eusinteger_t (*)())((((eusinteger_t)ifunc)&0xffff0000)
+      | (intval(code->c.fcode.entry2)&0x0000ffff));
+#endif
     /* R.Hanai 090726 */
   }
   while (iscons(paramtypes)) {
@@ -1306,13 +1315,13 @@ pointer args[];
   if (resulttype==K_FLOAT || resulttype==K_FLOAT32) {
     union {
       eusfloat_t f;
-#if __ARM_ARCH==4
+#if __ARM_ARCH==4 || __ARM_ARCH==5
       eusinteger_t i;    // ARM 32bit armel
 #else
       eusfloat_t i;  // Intel 32bit x86
 #endif
     } n;
-#if __ARM_ARCH==4
+#if __ARM_ARCH==4 || __ARM_ARCH==5
     typedef eusinteger_t ifunc_ret_type;
 #else
     typedef double ifunc_ret_type;
diff --git a/lisp/c/makes.c b/lisp/c/makes.c
index a4638a2d..8c243f87 100644
--- a/lisp/c/makes.c
+++ b/lisp/c/makes.c
@@ -501,6 +501,9 @@ int size;
   mod->c.ldmod.symtab=NIL;
   mod->c.ldmod.objname=NIL;
   mod->c.ldmod.handle=NIL;
+#if ARM
+  mod->c.ldmod.handle2=NIL;
+#endif
   return(mod);}
 
 pointer makeclosure(code,quote,f,e0,e1,e2)
diff --git a/lisp/c/unixcall.c b/lisp/c/unixcall.c
index 17766067..d9f3cf9c 100644
--- a/lisp/c/unixcall.c
+++ b/lisp/c/unixcall.c
@@ -132,7 +132,7 @@ pointer LOCALTIME(ctx,n,argv)
 register context *ctx;
 int n;
 pointer argv[];
-{ long clock;
+{ time_t clock;  /* sizoef time(0) is machine dependent and may differ from long */
   struct tm *tms;
   pointer timevec;
   pointer *tv;
@@ -203,6 +203,9 @@ register pointer argv[];
 #else
   atp=asctime_r(tms,at,ASCTIME_STRLEN);	/* asctime --> asctime_r */
 #endif
+  if (atp == NULL) {
+    error(E_USER,(pointer)strerror(errno));
+  }
   return(makestring(atp,strlen(atp)));}
 
 #if !Solaris2
@@ -211,16 +214,28 @@ pointer GETRUSAGE(ctx,n,argv)
 register context *ctx;
 int n; pointer argv[];
 { register int who,i;
-  long rusage[18];
+  struct rusage usage;
   eusfloat_t utime,stime;
   register pointer r=NIL;
   numunion nu;
-
   ckarg(1); who=ckintval(argv[0]);
-  getrusage(who,(struct rusage *)rusage);
-  utime=rusage[0]+rusage[1]*1.0e-6;
-  stime=rusage[2]+rusage[3]*1.0e-6;
-  for (i=17; i>=4; i--) r=cons(ctx,makeint(rusage[i]),r);
+  getrusage(who,&usage);
+  utime=usage.ru_utime.tv_sec+usage.ru_utime.tv_usec*1.0e-6;
+  stime=usage.ru_stime.tv_sec+usage.ru_stime.tv_usec*1.0e-6;
+  r = cons(ctx, makeint(usage.ru_nivcsw), r); // 4
+  r = cons(ctx, makeint(usage.ru_nvcsw), r); // 5
+  r = cons(ctx, makeint(usage.ru_nsignals), r); // 6
+  r = cons(ctx, makeint(usage.ru_msgrcv), r); // 7
+  r = cons(ctx, makeint(usage.ru_msgsnd), r); // 8
+  r = cons(ctx, makeint(usage.ru_oublock), r); // 9
+  r = cons(ctx, makeint(usage.ru_inblock), r); // 10
+  r = cons(ctx, makeint(usage.ru_nswap), r); // 11
+  r = cons(ctx, makeint(usage.ru_majflt), r); // 12
+  r = cons(ctx, makeint(usage.ru_minflt), r); // 13
+  r = cons(ctx, makeint(usage.ru_isrss), r); // 14
+  r = cons(ctx, makeint(usage.ru_idrss), r); // 15
+  r = cons(ctx, makeint(usage.ru_ixrss), r); // 16
+  r = cons(ctx, makeint(usage.ru_maxrss), r); // 17
   r=cons(ctx,makeflt(stime),r); r=cons(ctx,makeflt(utime),r);
   /*(utime stime maxrss ixrss idrss isrss page-reclaims page-faults swap
 	inblock outblock msgsnd msgrcv nsignals
diff --git a/lisp/xwindow/xforeign.c.c b/lisp/xwindow/xforeign.c.c
index aa9a2e58..9ceff2b1 100644
--- a/lisp/xwindow/xforeign.c.c
+++ b/lisp/xwindow/xforeign.c.c
@@ -433,7 +433,17 @@ char *xentry;
      dlhandle=(eusinteger_t)dlopen("libX11.dylib", RTLD_LAZY);
    entry=(eusinteger_t)dlsym((void *)dlhandle, xentry);
 #else
-  entry=(eusinteger_t)dlsym((void *)((eusinteger_t)(sysmod->c.ldmod.handle) & ~3), xentry);
+  eusinteger_t dlhandle = (eusinteger_t)(sysmod->c.ldmod.handle) & ~3;
+#if ARM
+  if ( sysmod->c.ldmod.handle2 != NIL ) {
+#if (WORD_SIZE == 64)
+    dlhandle = (dlhandle & 0xffffffff00000000) | (intval(sysmod->c.ldmod.handle2) & 0x00000000ffffffff);
+#else
+    dlhandle = (dlhandle & 0xffff0000) | (intval(sysmod->c.ldmod.handle2) & 0x0000ffff);
+#endif
+  }
+#endif
+  entry=(eusinteger_t)dlsym((void *)(dlhandle), xentry);
 #endif
   if (entry){
     xsym=intern(ctx,lname, len-1, xpkg);
diff --git a/test/time.l b/test/time.l
index 4d9353b2..cde956c0 100644
--- a/test/time.l
+++ b/test/time.l
@@ -62,6 +62,14 @@
 
 )
 
+(deftest test-asctime
+  ;; asctime segfaults on arm32:sid
+  (unix::asctime (unix::localtime)) ;; check if asctime works
+  (assert (string=
+	   (unix::asctime #(41 26 15 27 8 125 6 269 nil ("JST" "JST")))
+	   (format nil "Sat Sep 27 15:26:41 2025~%")))
+)
+
 (eval-when (load eval)
   (run-all-tests)
   (exit))
