Alexandre Julliard : ntdll: Fix handling of floating point arguments in relay debugging on ARM.

Alexandre Julliard julliard at winehq.org
Thu Dec 14 15:31:52 CST 2017


Module: wine
Branch: master
Commit: 5e3534ee411a8c5baea5022705eac0e3c7f3cc70
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=5e3534ee411a8c5baea5022705eac0e3c7f3cc70

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Thu Dec 14 11:44:57 2017 +0100

ntdll: Fix handling of floating point arguments in relay debugging on ARM.

Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/ntdll/relay.c       | 114 ++++++++++++++++++++++++++++++++++-------------
 tools/winebuild/spec32.c |  16 +++----
 2 files changed, 92 insertions(+), 38 deletions(-)

diff --git a/dlls/ntdll/relay.c b/dlls/ntdll/relay.c
index 5d78420..a0c3cb1 100644
--- a/dlls/ntdll/relay.c
+++ b/dlls/ntdll/relay.c
@@ -468,6 +468,10 @@ DECLSPEC_HIDDEN void * WINAPI relay_trace_entry( struct relay_descr *descr, unsi
     struct relay_private_data *data = descr->private;
     struct relay_entry_point *entry_point = data->entry_points + ordinal;
     unsigned int i, pos;
+#ifndef __SOFTFP__
+    unsigned int float_pos = 0, double_pos = 0;
+    const union fpregs { float s[16]; double d[8]; } *fpstack = (const union fpregs *)stack - 1;
+#endif
 
     TRACE( "\1Call %s(", func_name( data, ordinal ));
 
@@ -476,6 +480,7 @@ DECLSPEC_HIDDEN void * WINAPI relay_trace_entry( struct relay_descr *descr, unsi
         switch (arg_types[i])
         {
         case 'j': /* int64 */
+            pos = (pos + 1) & ~1;
             TRACE( "%x%08x", stack[pos+1], stack[pos] );
             pos += 2;
             break;
@@ -489,6 +494,30 @@ DECLSPEC_HIDDEN void * WINAPI relay_trace_entry( struct relay_descr *descr, unsi
         case 'w': /* wstr */
             trace_string_w( stack[pos++] );
             break;
+        case 'f': /* float */
+#ifndef __SOFTFP__
+            if (!(float_pos % 2)) float_pos = max( float_pos, double_pos * 2 );
+            if (float_pos < 16)
+            {
+                TRACE( "%g", fpstack->s[float_pos++] );
+                break;
+            }
+#endif
+            TRACE( "%g", *(const float *)&stack[pos++] );
+            break;
+        case 'd': /* double */
+#ifndef __SOFTFP__
+            double_pos = max( (float_pos + 1) / 2, double_pos );
+            if (double_pos < 8)
+            {
+                TRACE( "%g", fpstack->d[double_pos++] );
+                break;
+            }
+#endif
+            pos = (pos + 1) & ~1;
+            TRACE( "%g", *(const double *)&stack[pos] );
+            pos += 2;
+            break;
         case 'i': /* long */
         default:
             TRACE( "%08x", stack[pos++] );
@@ -496,6 +525,14 @@ DECLSPEC_HIDDEN void * WINAPI relay_trace_entry( struct relay_descr *descr, unsi
         }
         if (!is_ret_val( arg_types[i+1] )) TRACE( "," );
     }
+
+#ifndef __SOFTFP__
+    if (float_pos || double_pos)
+    {
+        pos |= 0x80000000;
+        stack = (const DWORD *)fpstack;  /* retaddr is below the fp regs */
+    }
+#endif
     *nb_args = pos;
     TRACE( ") ret=%08x\n", stack[-1] );
     return entry_point->orig_func;
@@ -519,39 +556,56 @@ DECLSPEC_HIDDEN void WINAPI relay_trace_exit( struct relay_descr *descr, unsigne
         TRACE( " retval=%08x ret=%08x\n", (UINT)retval, retaddr );
 }
 
-extern LONGLONG CDECL call_entry_point( void *func, int nb_args, const DWORD *args );
-__ASM_GLOBAL_FUNC( call_entry_point,
+extern LONGLONG WINAPI relay_call( struct relay_descr *descr, unsigned int idx, const DWORD *stack );
+__ASM_GLOBAL_FUNC( relay_call,
                    ".arm\n\t"
-                   "push {r4, r5, LR}\n\t"
-                   "mov r4, r0\n\t"
-                   "mov r5, SP\n\t"
+                   "push {r4-r8,lr}\n\t"
+                   "sub sp, #16\n\t"
+                   "mov r6, r2\n\t"
+                   "add r3, sp, #12\n\t"
+                   "mov r7, r0\n\t"
+                   "mov r8, r1\n\t"
+                   "bl " __ASM_NAME("relay_trace_entry") "\n\t"
+                   "mov ip, r0\n\t"  /* entry point */
+                   "mov r5, sp\n\t"
+                   "ldr r1, [sp, #12]\n\t"  /* number of args */
                    "lsl r3, r1, #2\n\t"
-                   "sub SP, SP, r3\n\t"
-                   "and SP, SP, #~7\n"
-                   "1:\tsub r3, r3, #4\n\t"
+                   "subs r3, #16\n\t"   /* first 4 args are in registers */
+                   "ble 2f\n\t"
+                   "sub sp, r3\n\t"
+                   "and sp, #~7\n"
+                   "add r2, r6, #16\n\t"   /* skip r0-r3 */
+                   "1:\tsubs r3, r3, #4\n\t"
                    "ldr r0, [r2, r3]\n\t"
-                   "str r0, [SP, r3]\n\t"
-                   "cmp r3, #0\n\t"
-                   "bgt 1b\n\t"
-                   "cmp r1, #0\n\t"
-                   "beq 3f\n\t"
-                   "cmp r1, #2\n\t"
-                   "bgt 2f\n\t"
-                   "pop {r0-r1}\n\t"
-                   "b 3f\n"
-                   "2:\tpop {r0-r3}\n"
-                   "3:\tblx r4\n\t"
-                   "mov SP, r5\n\t"
-                   "pop {r4, r5, PC}" )
-
-static LONGLONG WINAPI relay_call( struct relay_descr *descr, unsigned int idx, const DWORD *stack )
-{
-    unsigned int nb_args;
-    void *func = relay_trace_entry( descr, idx, stack, &nb_args );
-    LONGLONG ret = call_entry_point( func, nb_args, stack );
-    relay_trace_exit( descr, idx, stack[-1], ret );
-    return ret;
-}
+                   "str r0, [sp, r3]\n\t"
+                   "bgt 1b\n"
+                   "2:\t"
+#ifndef __SOFTFP__
+                   "tst r1, #0x80000000\n\t"
+                   "ldm r6, {r0-r3}\n\t"
+                   "vldmdbne r6!, {s0-s15}\n\t"
+#else
+                   "ldm r6, {r0-r3}\n\t"
+#endif
+                   "blx ip\n\t"
+                   "mov sp, r5\n\t"
+                   "ldr r2, [r6, #-4]\n\t"  /* retaddr */
+                   "mov r4, r0\n\t"
+                   "mov r5, r1\n\t"
+                   "mov r0, r7\n\t"
+                   "mov r1, r8\n\t"
+                   "strd r4, [sp]\n\t"
+#ifndef __SOFTFP__
+                   "vstr d0, [sp, #8]\n\t"  /* preserve floating point retval */
+                   "bl " __ASM_NAME("relay_trace_exit") "\n\t"
+                   "vldr d0, [sp, #8]\n\t"
+#else
+                   "bl " __ASM_NAME("relay_trace_exit") "\n\t"
+#endif
+                   "mov r0, r4\n\t"
+                   "mov r1, r5\n\t"
+                   "add sp, #16\n\t"
+                   "pop {r4-r8,pc}" )
 
 #elif defined(__aarch64__)
 
diff --git a/tools/winebuild/spec32.c b/tools/winebuild/spec32.c
index d028726..3552eca 100644
--- a/tools/winebuild/spec32.c
+++ b/tools/winebuild/spec32.c
@@ -255,16 +255,16 @@ static void output_relay_debug( DLLSPEC *spec )
         case CPU_ARM:
         {
             unsigned int mask, val, count = 0;
-            unsigned int stack_size = min( 16, (get_args_size( odp ) + 7) & ~7 );
+            int j, has_float = 0;
+
+            if (strcmp( float_abi_option, "soft" ))
+                for (j = 0; j < odp->u.func.nb_args && !has_float; j++)
+                    has_float = is_float_arg( odp, j );
 
             val = (odp->u.func.args_str_offset << 16) | (i - spec->base);
-            switch (stack_size)
-            {
-            case 16: output( "\tpush {r0-r3}\n" ); break;
-            case 8:  output( "\tpush {r0-r1}\n" ); break;
-            case 0:  break;
-            }
+            output( "\tpush {r0-r3}\n" );
             output( "\tmov r2, SP\n");
+            if (has_float) output( "\tvpush {s0-s15}\n" );
             output( "\tpush {LR}\n" );
             output( "\tsub SP, #4\n");
             for (mask = 0xff; mask; mask <<= 8)
@@ -275,7 +275,7 @@ static void output_relay_debug( DLLSPEC *spec )
             output( "\tldr IP, [r0, #4]\n");
             output( "1:\tblx IP\n");
             output( "\tldr IP, [SP, #4]\n" );
-            output( "\tadd SP, #%u\n", stack_size + 8 );
+            output( "\tadd SP, #%u\n", 24 + (has_float ? 64 : 0) );
             output( "\tbx IP\n");
             output( "2:\t.long .L__wine_spec_relay_descr-1b\n" );
             break;




More information about the wine-cvs mailing list