Module: wine Branch: master Commit: c1a700f018ae86b31c61b0ce4e932f335a6f5081 URL: https://source.winehq.org/git/wine.git/?a=commit;h=c1a700f018ae86b31c61b0ce4...
Author: Alexandre Julliard julliard@winehq.org Date: Sat Jan 16 11:05:38 2021 +0100
winebuild: Generate Thumb2-compatible assembly code on ARM.
Signed-off-by: Alexandre Julliard julliard@winehq.org
---
tools/winebuild/import.c | 58 ++++++++++++++++++++++++------------------------ tools/winebuild/main.c | 2 ++ tools/winebuild/spec32.c | 8 ++++--- tools/winebuild/utils.c | 11 ++++++++- 4 files changed, 46 insertions(+), 33 deletions(-)
diff --git a/tools/winebuild/import.c b/tools/winebuild/import.c index e6dff564f79..00b6f19ec98 100644 --- a/tools/winebuild/import.c +++ b/tools/winebuild/import.c @@ -755,9 +755,10 @@ 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,1f\n"); - output( "\tldr PC,[PC,IP]\n" ); - output( "1:\t.long %s+%u-(1b+4)\n", table, pos ); + output( "\tldr ip, 2f\n"); + output( "1:\tadd ip, pc\n" ); + output( "\tldr pc, [ip]\n"); + output( "2:\t.long %s+%u-1b-%u\n", table, pos, thumb_mode ? 4 : 8 ); break; case CPU_ARM64: output( "\tadrp x16, %s\n", arm64_page( table ) ); @@ -956,7 +957,7 @@ static void output_delayed_imports( const DLLSPEC *spec ) struct import_func *func = &import->imports[j]; const char *name = func->name ? func->name : func->export_name; output( "__imp_%s:\n", asm_name( name )); - output( "\t%s .L__wine_delay_imp_%s_%s\n", + output( "\t%s __wine_delay_imp_%s_%s\n", get_asm_ptr_keyword(), import->c_name, name ); } } @@ -1066,13 +1067,10 @@ static void output_delayed_import_thunks( const DLLSPEC *spec ) case CPU_ARM: 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( "\tbl %s\n", asm_name("__wine_spec_delay_load") ); + output( "\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,#-80]!\n" ); @@ -1153,7 +1151,8 @@ static void output_delayed_import_thunks( const DLLSPEC *spec ) struct import_func *func = &import->imports[j]; const char *name = func->name ? func->name : func->export_name;
- output( ".L__wine_delay_imp_%s_%s:\n", import->c_name, name ); + if (thumb_mode) output( "\t.thumb_func\n" ); + output( "__wine_delay_imp_%s_%s:\n", import->c_name, name ); output_cfi( ".cfi_startproc" ); switch(target_cpu) { @@ -1349,14 +1348,13 @@ void output_stubs( DLLSPEC *spec ) output( "\tcall %s\n", asm_name("__wine_spec_unimplemented_stub") ); break; case CPU_ARM: - output( "\tldr r0,2f\n"); - output( "\tadd r0,PC\n"); - output( "\tldr r1,2f+4\n"); - output( "1:" ); - if (exp_name) output( "\tadd r1,PC\n"); + output( "\tldr r0,3f\n"); + output( "1:\tadd r0,PC\n"); + output( "\tldr r1,3f+4\n"); + if (exp_name) output( "2:\tadd r1,PC\n"); 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 ); + output( "3:\t.long .L__wine_spec_file_name-1b-%u\n", thumb_mode ? 4 : 8 ); + if (exp_name) output( "\t.long .L%s_string-2b-%u\n", name, thumb_mode ? 4 : 8 ); else output( "\t.long %u\n", odp->ordinal ); break; case CPU_ARM64: @@ -1566,28 +1564,30 @@ void output_syscalls( DLLSPEC *spec ) output( "\tstr ip, [sp, #4]\n" ); output( "\tstr sp, [r7]\n" ); /* syscall frame */ output( "\tldr r5, 7f\n"); - output( "\tadd r5, pc\n"); + output( "1:\tadd r5, pc\n"); output( "\tldrb r5, [r5, r4]\n" ); /* syscall args */ - output( "1:\tsubs r5, #16\n" ); /* first 4 args are in registers */ + output( "\tsubs r5, #16\n" ); /* first 4 args are in registers */ output( "\tble 3f\n" ); - output( "\tsub sp, r5\n" ); - output( "\tand sp, #~7\n" ); + output( "\tsub ip, sp, r5\n" ); + output( "\tand ip, #~7\n" ); + output( "\tmov sp, ip\n" ); output( "2:\tsubs r5, r5, #4\n" ); output( "\tldr ip, [r6, r5]\n" ); output( "\tstr ip, [sp, r5]\n" ); output( "\tbgt 2b\n" ); output( "3:\tldr r5, 6f\n"); - output( "\tadd r5, pc\n"); + output( "4:\tadd r5, pc\n"); output( "\tldr ip, [r5, r4, lsl #2]\n"); /* syscall table */ - output( "4:\tblx ip\n"); + output( "\tblx ip\n"); output( "\tmov ip, #0\n" ); output( "\tstr ip, [r7]\n" ); - output( "\tsub sp, r6, #40\n" ); + output( "\tsub ip, r6, #40\n" ); + output( "\tmov sp, ip\n" ); output( "\tpop {r5-r11,pc}\n" ); output( "5:\tldr r0, 9f\n" ); output( "\tpop {r5-r11,pc}\n" ); - output( "6:\t.long .Lsyscall_table-4b\n" ); - output( "7:\t.long .Lsyscall_args-1b\n" ); + output( "6:\t.long .Lsyscall_table-4b-%u\n", thumb_mode ? 4 : 8 ); + output( "7:\t.long .Lsyscall_args-1b-%u\n", thumb_mode ? 4 : 8 ); output( "8:\t.long %u\n", count ); output( "9:\t.long 0x%x\n", invalid_param ); break; @@ -1731,11 +1731,11 @@ void output_syscalls( DLLSPEC *spec ) output( "\tpush {r4,lr}\n" ); output( "\tldr r4, 3f\n"); output( "\tldr ip, 2f\n"); - output( "\tadd ip, pc\n"); + output( "1:\tadd ip, pc\n" ); output( "\tldr ip, [ip]\n"); - output( "1:\tblx ip\n"); + output( "\tblx ip\n"); output( "\tpop {r4,pc}\n" ); - output( "2:\t.long %s-1b\n", asm_name("__wine_syscall_dispatcher") ); + output( "2:\t.long %s-1b-%u\n", asm_name("__wine_syscall_dispatcher"), thumb_mode ? 4 : 8 ); output( "3:\t.long %u\n", i ); break; case CPU_ARM64: diff --git a/tools/winebuild/main.c b/tools/winebuild/main.c index 572b4d74ae7..abb94e27c03 100644 --- a/tools/winebuild/main.c +++ b/tools/winebuild/main.c @@ -244,6 +244,8 @@ static void set_target( const char *target ) }
free( spec ); + + if (target_cpu == CPU_ARM && target_platform == PLATFORM_WINDOWS) thumb_mode = 1; }
/* cleanup on program exit */ diff --git a/tools/winebuild/spec32.c b/tools/winebuild/spec32.c index a12e7d38aac..6d56cc01b6e 100644 --- a/tools/winebuild/spec32.c +++ b/tools/winebuild/spec32.c @@ -249,6 +249,7 @@ static void output_relay_debug( DLLSPEC *spec ) /* then the relay thunks */
output( "\t.text\n" ); + if (thumb_mode) output( "\t.thumb_func\n" ); output( "__wine_spec_relay_entry_points:\n" ); output( "\tnop\n" ); /* to avoid 0 offset */
@@ -306,6 +307,7 @@ static void output_relay_debug( DLLSPEC *spec )
val = (odp->u.func.args_str_offset << 16) | (i - spec->base); output( "\t.align %d\n", get_alignment(4) ); + if (thumb_mode) output( "\t.thumb_func\n" ); output( ".L__wine_spec_relay_entry_point_%d:\n", i ); output_cfi( ".cfi_startproc" ); output( "\tpush {r0-r3}\n" ); @@ -317,13 +319,13 @@ static void output_relay_debug( DLLSPEC *spec ) 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( "1:\tadd r0, PC\n"); output( "\tldr IP, [r0, #4]\n"); - output( "1:\tblx IP\n"); + output( "\tblx IP\n"); output( "\tldr IP, [SP, #4]\n" ); 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" ); + output( "2:\t.long .L__wine_spec_relay_descr-1b-%u\n", thumb_mode ? 4 : 8 ); output_cfi( ".cfi_endproc" ); break; } diff --git a/tools/winebuild/utils.c b/tools/winebuild/utils.c index 5cffc74accd..1a11d275cb3 100644 --- a/tools/winebuild/utils.c +++ b/tools/winebuild/utils.c @@ -690,6 +690,11 @@ void output_standard_file_header(void) output( "\t.globl @feat.00\n" ); output( ".set @feat.00, 1\n" ); } + if (thumb_mode) + { + output( "\t.syntax unified\n" ); + output( "\t.thumb\n" ); + } }
/* dump a byte stream into the assembly code */ @@ -1119,13 +1124,17 @@ const char *func_declaration( const char *func ) return ""; case PLATFORM_WINDOWS: free( buffer ); - buffer = strmake( ".def %s\n\t.scl 2\n\t.type 32\n\t.endef", asm_name(func) ); + buffer = strmake( ".def %s\n\t.scl 2\n\t.type 32\n\t.endef%s", asm_name(func), + thumb_mode ? "\n\t.thumb_func" : "" ); break; default: free( buffer ); switch(target_cpu) { case CPU_ARM: + buffer = strmake( ".type %s,%%function%s", func, + thumb_mode ? "\n\t.thumb_func" : "" ); + break; case CPU_ARM64: buffer = strmake( ".type %s,%%function", func ); break;