winebuild: Generate position-independent code for ARM.

This commit is contained in:
Alexandre Julliard 2014-02-11 20:46:25 +01:00
parent f4985e42b7
commit 4e4acd5f70
2 changed files with 50 additions and 51 deletions

View file

@ -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 ); output( "\tjmpq *%s+%d(%%rip)\n", table, pos );
break; break;
case CPU_ARM: case CPU_ARM:
output( "\tldr IP,[PC,#0]\n"); output( "\tldr IP,1f\n");
output( "\tldr PC,[IP,#%d]\n", pos); output( "\tldr PC,[PC,IP]\n" );
output( "\t.long %s\n", table ); output( "1:\t.long %s+%u-(1b+4)\n", table, pos );
break; break;
case CPU_ARM64: case CPU_ARM64:
output( "\tadr x9, 1f\n" ); output( "\tadr x9, 1f\n" );
@ -967,15 +967,15 @@ static void output_delayed_import_thunks( const DLLSPEC *spec )
output( "\tjmp *%%rax\n" ); output( "\tjmp *%%rax\n" );
break; break;
case CPU_ARM: case CPU_ARM:
output( "\tstmfd SP!, {r4-r10,FP,LR}\n" ); output( "\tpush {r0-r3,FP,LR}\n" );
output( "\tmov LR,PC\n"); output( "\tmov r0,IP\n" );
output( "\tadd LR,LR,#8\n"); output( "\tldr IP,2f\n");
output( "\tldr PC,[PC,#-4]\n"); output( "\tadd IP,PC\n");
output( "\t.long %s\n", asm_name("__wine_spec_delay_load") ); output( "\tblx IP\n");
output( "\tmov IP,r0\n"); output( "1:\tmov IP,r0\n");
output( "\tldmfd SP!, {r4-r10,FP,LR}\n" ); output( "\tpop {r0-r3,FP,LR}\n" );
output( "\tldmfd SP!, {r0-r3}\n" ); output( "\tbx IP\n");
output( "\tmov PC,IP\n"); output( "2:\t.long %s-1b\n", asm_name("__wine_spec_delay_load") );
break; break;
case CPU_ARM64: case CPU_ARM64:
output( "\tstp x29, x30, [sp,#-16]!\n" ); 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") ); output( "\tjmp %s\n", asm_name("__wine_delay_load_asm") );
break; break;
case CPU_ARM: case CPU_ARM:
output( "\tstmfd SP!, {r0-r3}\n" ); {
output( "\tmov r0, #%d\n", idx ); unsigned int mask, count = 0, val = (idx << 16) | j;
output( "\tmov r1, #16384\n" );
output( "\tmul r1, r0, r1\n" ); for (mask = 0xff; mask; mask <<= 8)
output( "\tmov r0, r1\n" ); if (val & mask) output( "\t%s IP,#%u\n", count++ ? "add" : "mov", val & mask );
output( "\tmov r1, #4\n" ); if (!count) output( "\tmov IP,#0\n" );
output( "\tmul r1, r0, r1\n" ); output( "\tb %s\n", asm_name("__wine_delay_load_asm") );
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") );
break; break;
}
case CPU_ARM64: case CPU_ARM64:
output( "\tstp x6, x7, [sp,#-80]!\n" ); output( "\tstp x6, x7, [sp,#-80]!\n" );
output( "\tstp x4, x5, [sp,#48]\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") ); output( "\tcall %s\n", asm_name("__wine_spec_unimplemented_stub") );
break; break;
case CPU_ARM: case CPU_ARM:
output( "\tldr r0,[PC,#0]\n"); output( "\tldr r0,2f\n");
output( "\tmov PC,PC\n"); output( "\tadd r0,PC\n");
output( "\t.long .L__wine_spec_file_name\n" ); output( "\tldr r1,2f+4\n");
output( "\tldr r1,[PC,#0]\n"); output( "1:" );
output( "\tmov PC,PC\n");
if (exp_name) if (exp_name)
{ {
output( "\t.long .L%s_string\n", name ); output( "\tadd r1,PC\n");
count++; count++;
} }
else
output( "\t.long %d\n", odp->ordinal );
output( "\tbl %s\n", asm_name("__wine_spec_unimplemented_stub") ); 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; break;
default: default:
assert(0); assert(0);

View file

@ -210,32 +210,34 @@ static void output_relay_debug( DLLSPEC *spec )
break; break;
case CPU_ARM: 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 16: output( "\tpush {r0-r3}\n" ); break;
case 3: output( "\tpush {r0-r2}\n" ); break; case 8: output( "\tpush {r0-r1}\n" ); break;
case 2: output( "\tpush {r0-r1}\n" ); break;
case 1: output( "\tpush {r0}\n" ); break;
case 0: break; case 0: break;
} }
output( "\tpush {LR}\n" ); output( "\tpush {LR}\n" );
output( "\tmov r2, SP\n"); output( "\tmov r2, SP\n");
if (odp->flags & FLAG_RET64) flags |= 1; output( "\tsub SP, #4\n");
output( "\tmov r1, #%u\n", (flags << 24) ); for (mask = 0xff; mask; mask <<= 8)
if (args) output( "\tadd r1, #%u\n", (args << 16) ); if (val & mask) output( "\t%s r1,#%u\n", count++ ? "add" : "mov", val & mask );
if ((i - spec->base) & 0xf000) output( "\tadd r1, #%u\n", (i - spec->base) & 0xf000 ); if (!count) output( "\tmov r1,#0\n" );
if ((i - spec->base) & 0x0f00) output( "\tadd r1, #%u\n", (i - spec->base) & 0x0f00 ); output( "\tldr r0, 2f\n");
if ((i - spec->base) & 0x00f0) output( "\tadd r1, #%u\n", (i - spec->base) & 0x00f0 ); output( "\tadd r0, PC\n");
if ((i - spec->base) & 0x000f) output( "\tadd r1, #%u\n", (i - spec->base) & 0x000f ); output( "\tldr IP, [r0, #4]\n");
output( "\tldr r0, [PC, #0]\n"); output( "1:\tblx IP\n");
output( "\tmov PC, PC\n"); output( "\tldr IP, [SP, #4]\n" );
output( "\t.long .L__wine_spec_relay_descr\n" ); output( "\tadd SP, #%u\n", stack_size + 8 );
output( "\tldr r3, [r0, #4]\n"); output( "\tbx IP\n");
output( "\tblx r3\n"); output( "2:\t.long .L__wine_spec_relay_descr-1b\n" );
output( "\tpop {r3}\n" );
if (args) output( "\tadd SP, SP, #%u\n", min(args*4, 16) );
output( "\tbx r3\n");
break; break;
}
case CPU_x86_64: case CPU_x86_64:
output( "\tsubq $40,%%rsp\n" ); output( "\tsubq $40,%%rsp\n" );