Alexandre Julliard : winebuild: Generate position-independent code for ARM.

Alexandre Julliard julliard at winehq.org
Wed Feb 12 13:44:37 CST 2014


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

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Tue Feb 11 20:46:25 2014 +0100

winebuild: Generate position-independent code for ARM.

---

 tools/winebuild/import.c |   59 ++++++++++++++++++++++------------------------
 tools/winebuild/spec32.c |   42 +++++++++++++++++----------------
 2 files changed, 50 insertions(+), 51 deletions(-)

diff --git a/tools/winebuild/import.c b/tools/winebuild/import.c
index f8de47e..6bafd86 100644
--- a/tools/winebuild/import.c
+++ b/tools/winebuild/import.c
@@ -650,9 +650,9 @@ static void output_import_thunk( const char *name, const char *table, int pos )
         output( "\tjmpq *%s+%d(%%rip)\n", table, pos );
         break;
     case CPU_ARM:
-        output( "\tldr IP,[PC,#0]\n");
-        output( "\tldr PC,[IP,#%d]\n", pos);
-        output( "\t.long %s\n", table );
+        output( "\tldr IP,1f\n");
+        output( "\tldr PC,[PC,IP]\n" );
+        output( "1:\t.long %s+%u-(1b+4)\n", table, pos );
         break;
     case CPU_ARM64:
         output( "\tadr x9, 1f\n" );
@@ -967,15 +967,15 @@ static void output_delayed_import_thunks( const DLLSPEC *spec )
         output( "\tjmp *%%rax\n" );
         break;
     case CPU_ARM:
-        output( "\tstmfd  SP!, {r4-r10,FP,LR}\n" );
-        output( "\tmov LR,PC\n");
-        output( "\tadd LR,LR,#8\n");
-        output( "\tldr PC,[PC,#-4]\n");
-        output( "\t.long %s\n", asm_name("__wine_spec_delay_load") );
-        output( "\tmov IP,r0\n");
-        output( "\tldmfd  SP!, {r4-r10,FP,LR}\n" );
-        output( "\tldmfd  SP!, {r0-r3}\n" );
-        output( "\tmov PC,IP\n");
+        output( "\tpush {r0-r3,FP,LR}\n" );
+        output( "\tmov r0,IP\n" );
+        output( "\tldr IP,2f\n");
+        output( "\tadd IP,PC\n");
+        output( "\tblx IP\n");
+        output( "1:\tmov IP,r0\n");
+        output( "\tpop {r0-r3,FP,LR}\n" );
+        output( "\tbx IP\n");
+        output( "2:\t.long %s-1b\n", asm_name("__wine_spec_delay_load") );
         break;
     case CPU_ARM64:
         output( "\tstp x29, x30, [sp,#-16]!\n" );
@@ -1067,18 +1067,15 @@ static void output_delayed_import_thunks( const DLLSPEC *spec )
                 output( "\tjmp %s\n", asm_name("__wine_delay_load_asm") );
                 break;
             case CPU_ARM:
-                output( "\tstmfd  SP!, {r0-r3}\n" );
-                output( "\tmov r0, #%d\n", idx );
-                output( "\tmov r1, #16384\n" );
-                output( "\tmul r1, r0, r1\n" );
-                output( "\tmov r0, r1\n" );
-                output( "\tmov r1, #4\n" );
-                output( "\tmul r1, r0, r1\n" );
-                output( "\tmov r0, r1\n" );
-                output( "\tadd r0, #%d\n", j );
-                output( "\tldr PC,[PC,#-4]\n");
-                output( "\t.long %s\n", asm_name("__wine_delay_load_asm") );
+            {
+                unsigned int mask, count = 0, val = (idx << 16) | j;
+
+                for (mask = 0xff; mask; mask <<= 8)
+                    if (val & mask) output( "\t%s IP,#%u\n", count++ ? "add" : "mov", val & mask );
+                if (!count) output( "\tmov IP,#0\n" );
+                output( "\tb %s\n", asm_name("__wine_delay_load_asm") );
                 break;
+            }
             case CPU_ARM64:
                 output( "\tstp x6, x7, [sp,#-80]!\n" );
                 output( "\tstp x4, x5, [sp,#48]\n" );
@@ -1268,19 +1265,19 @@ void output_stubs( DLLSPEC *spec )
             output( "\tcall %s\n", asm_name("__wine_spec_unimplemented_stub") );
             break;
         case CPU_ARM:
-            output( "\tldr r0,[PC,#0]\n");
-            output( "\tmov PC,PC\n");
-            output( "\t.long .L__wine_spec_file_name\n" );
-            output( "\tldr r1,[PC,#0]\n");
-            output( "\tmov PC,PC\n");
+            output( "\tldr r0,2f\n");
+            output( "\tadd r0,PC\n");
+            output( "\tldr r1,2f+4\n");
+            output( "1:" );
             if (exp_name)
             {
-                output( "\t.long .L%s_string\n", name );
+                output( "\tadd r1,PC\n");
                 count++;
             }
-            else
-                output( "\t.long %d\n", odp->ordinal );
             output( "\tbl %s\n", asm_name("__wine_spec_unimplemented_stub") );
+            output( "2:\t.long .L__wine_spec_file_name-1b\n" );
+            if (exp_name) output( "\t.long .L%s_string-2b\n", name );
+            else output( "\t.long %u\n", odp->ordinal );
             break;
         default:
             assert(0);
diff --git a/tools/winebuild/spec32.c b/tools/winebuild/spec32.c
index 0ed38ed..35fe144 100644
--- a/tools/winebuild/spec32.c
+++ b/tools/winebuild/spec32.c
@@ -210,32 +210,34 @@ static void output_relay_debug( DLLSPEC *spec )
             break;
 
         case CPU_ARM:
-            switch (args)
+        {
+            unsigned int mask, val, count = 0;
+            unsigned int stack_size = min( 16, (args * 4 + 7) & ~7 );
+
+            if (odp->flags & FLAG_RET64) flags |= 1;
+            val = (flags << 24) | (args << 16) | (i - spec->base);
+            switch (stack_size)
             {
-            default: output( "\tpush {r0-r3}\n" ); break;
-            case 3:  output( "\tpush {r0-r2}\n" ); break;
-            case 2:  output( "\tpush {r0-r1}\n" ); break;
-            case 1:  output( "\tpush {r0}\n" ); break;
+            case 16: output( "\tpush {r0-r3}\n" ); break;
+            case 8:  output( "\tpush {r0-r1}\n" ); break;
             case 0:  break;
             }
             output( "\tpush {LR}\n" );
             output( "\tmov r2, SP\n");
-            if (odp->flags & FLAG_RET64) flags |= 1;
-            output( "\tmov r1, #%u\n", (flags << 24) );
-            if (args) output( "\tadd r1, #%u\n", (args << 16) );
-            if ((i - spec->base) & 0xf000) output( "\tadd r1, #%u\n", (i - spec->base) & 0xf000 );
-            if ((i - spec->base) & 0x0f00) output( "\tadd r1, #%u\n", (i - spec->base) & 0x0f00 );
-            if ((i - spec->base) & 0x00f0) output( "\tadd r1, #%u\n", (i - spec->base) & 0x00f0 );
-            if ((i - spec->base) & 0x000f) output( "\tadd r1, #%u\n", (i - spec->base) & 0x000f );
-            output( "\tldr r0, [PC, #0]\n");
-            output( "\tmov PC, PC\n");
-            output( "\t.long .L__wine_spec_relay_descr\n" );
-            output( "\tldr r3, [r0, #4]\n");
-            output( "\tblx r3\n");
-            output( "\tpop {r3}\n" );
-            if (args) output( "\tadd SP, SP, #%u\n", min(args*4, 16) );
-            output( "\tbx r3\n");
+            output( "\tsub SP, #4\n");
+            for (mask = 0xff; mask; mask <<= 8)
+                if (val & mask) output( "\t%s r1,#%u\n", count++ ? "add" : "mov", val & mask );
+            if (!count) output( "\tmov r1,#0\n" );
+            output( "\tldr r0, 2f\n");
+            output( "\tadd r0, PC\n");
+            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( "\tbx IP\n");
+            output( "2:\t.long .L__wine_spec_relay_descr-1b\n" );
             break;
+        }
 
         case CPU_x86_64:
             output( "\tsubq $40,%%rsp\n" );




More information about the wine-cvs mailing list