Commit c1a700f0 authored by Alexandre Julliard's avatar Alexandre Julliard

winebuild: Generate Thumb2-compatible assembly code on ARM.

parent defa3305
......@@ -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:
......
......@@ -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 */
......
......@@ -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;
}
......
......@@ -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;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment