From 4e4acd5f705c770b7c361605e11d9d7c044ca0e8 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Tue, 11 Feb 2014 20:46:25 +0100 Subject: [PATCH] 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 f8de47ead44..6bafd86c27a 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 0ed38edd40d..35fe14479ec 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" );