mirror of
git://source.winehq.org/git/wine.git
synced 2024-10-14 21:27:19 +00:00
widl: Output register parameter assignments on ARM platforms.
This commit is contained in:
parent
30a7054879
commit
235f76594e
|
@ -1372,6 +1372,129 @@ int is_interpreted_func( const type_t *iface, const var_t *func )
|
||||||
return interpreted_mode;
|
return interpreted_mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* replace consecutive params code by a repeat sequence: 0x9d code<1> repeat_count<2> */
|
||||||
|
static unsigned int compress_params_array( unsigned char *params, unsigned int count )
|
||||||
|
{
|
||||||
|
unsigned int i, j;
|
||||||
|
|
||||||
|
for (i = 0; i + 4 <= count; i++)
|
||||||
|
{
|
||||||
|
for (j = 1; i + j < count; j++) if (params[i + j] != params[i]) break;
|
||||||
|
if (j < 4) continue;
|
||||||
|
params[i] = 0x9d;
|
||||||
|
params[i + 2] = j & 0xff;
|
||||||
|
params[i + 3] = j >> 8;
|
||||||
|
memmove( params + i + 4, params + i + j, count - (i + j) );
|
||||||
|
count -= j - 4;
|
||||||
|
i += 3;
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* fill the parameters array for the procedure extra data on ARM platforms */
|
||||||
|
static unsigned int fill_params_array( const type_t *iface, const var_t *func,
|
||||||
|
unsigned char *params, unsigned int count )
|
||||||
|
{
|
||||||
|
unsigned int reg_count = 0, float_count = 0, double_count = 0, stack_pos = 0, offset = 0;
|
||||||
|
var_list_t *args = type_function_get_args( func->declspec.type );
|
||||||
|
enum type_basic_type type;
|
||||||
|
unsigned int size, pos, align;
|
||||||
|
var_t *var;
|
||||||
|
|
||||||
|
memset( params, 0x9f /* padding */, count );
|
||||||
|
|
||||||
|
if (is_object( iface ))
|
||||||
|
{
|
||||||
|
params[0] = 0x80 + reg_count++;
|
||||||
|
offset += pointer_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (args) LIST_FOR_EACH_ENTRY( var, args, var_t, entry )
|
||||||
|
{
|
||||||
|
type = TYPE_BASIC_LONG;
|
||||||
|
if (type_get_type( var->declspec.type ) == TYPE_BASIC)
|
||||||
|
type = type_basic_get_type( var->declspec.type );
|
||||||
|
|
||||||
|
size = get_stack_size( var, &align, NULL );
|
||||||
|
offset = ROUND_SIZE( offset, align );
|
||||||
|
pos = offset / pointer_size;
|
||||||
|
|
||||||
|
if (target.cpu == CPU_ARM64)
|
||||||
|
{
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case TYPE_BASIC_FLOAT:
|
||||||
|
case TYPE_BASIC_DOUBLE:
|
||||||
|
if (double_count >= 8) break;
|
||||||
|
params[pos] = 0x88 + double_count++;
|
||||||
|
offset += size;
|
||||||
|
continue;
|
||||||
|
|
||||||
|
default:
|
||||||
|
reg_count = ROUND_SIZE( reg_count, align / pointer_size );
|
||||||
|
if (reg_count > 8 - size / pointer_size) break;
|
||||||
|
while (size)
|
||||||
|
{
|
||||||
|
params[pos++] = 0x80 + reg_count++;
|
||||||
|
offset += pointer_size;
|
||||||
|
size -= pointer_size;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else /* CPU_ARM */
|
||||||
|
{
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case TYPE_BASIC_FLOAT:
|
||||||
|
if (!(float_count % 2)) float_count = max( float_count, double_count * 2 );
|
||||||
|
if (float_count >= 16)
|
||||||
|
{
|
||||||
|
stack_pos = ROUND_SIZE( stack_pos, align );
|
||||||
|
params[pos] = 0x100 - (offset - stack_pos) / pointer_size;
|
||||||
|
stack_pos += size;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
params[pos] = 0x84 + float_count++;
|
||||||
|
}
|
||||||
|
offset += size;
|
||||||
|
continue;
|
||||||
|
|
||||||
|
case TYPE_BASIC_DOUBLE:
|
||||||
|
double_count = max( double_count, (float_count + 1) / 2 );
|
||||||
|
if (double_count >= 8) break;
|
||||||
|
params[pos] = 0x84 + 2 * double_count;
|
||||||
|
params[pos + 1] = 0x84 + 2 * double_count + 1;
|
||||||
|
double_count++;
|
||||||
|
offset += size;
|
||||||
|
continue;
|
||||||
|
|
||||||
|
default:
|
||||||
|
reg_count = ROUND_SIZE( reg_count, align / pointer_size );
|
||||||
|
if (reg_count <= 4 - size / pointer_size || !stack_pos)
|
||||||
|
{
|
||||||
|
while (size && reg_count < 4)
|
||||||
|
{
|
||||||
|
params[pos++] = 0x80 + reg_count++;
|
||||||
|
offset += pointer_size;
|
||||||
|
size -= pointer_size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
stack_pos = ROUND_SIZE( stack_pos, align );
|
||||||
|
memset( params + pos, 0x100 - (offset - stack_pos) / pointer_size, size / pointer_size );
|
||||||
|
stack_pos += size;
|
||||||
|
offset += size;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (count && params[count - 1] == 0x9f) count--;
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
static void write_proc_func_interp( FILE *file, int indent, const type_t *iface,
|
static void write_proc_func_interp( FILE *file, int indent, const type_t *iface,
|
||||||
const var_t *func, unsigned int *offset,
|
const var_t *func, unsigned int *offset,
|
||||||
unsigned short num_proc )
|
unsigned short num_proc )
|
||||||
|
@ -1390,6 +1513,7 @@ static void write_proc_func_interp( FILE *file, int indent, const type_t *iface,
|
||||||
unsigned int stack_size = 0;
|
unsigned int stack_size = 0;
|
||||||
unsigned int stack_offset = 0;
|
unsigned int stack_offset = 0;
|
||||||
unsigned int stack_align;
|
unsigned int stack_align;
|
||||||
|
unsigned int extra_size = 0;
|
||||||
unsigned short param_num = 0;
|
unsigned short param_num = 0;
|
||||||
unsigned short handle_stack_offset = 0;
|
unsigned short handle_stack_offset = 0;
|
||||||
unsigned short handle_param_num = 0;
|
unsigned short handle_param_num = 0;
|
||||||
|
@ -1477,16 +1601,21 @@ static void write_proc_func_interp( FILE *file, int indent, const type_t *iface,
|
||||||
print_file( file, indent, "NdrFcShort(0x%x),\t/* server buffer = %u */\n", size, size );
|
print_file( file, indent, "NdrFcShort(0x%x),\t/* server buffer = %u */\n", size, size );
|
||||||
print_file( file, indent, "0x%02x,\n", oi2_flags );
|
print_file( file, indent, "0x%02x,\n", oi2_flags );
|
||||||
print_file( file, indent, "0x%02x,\t/* %u params */\n", nb_args, nb_args );
|
print_file( file, indent, "0x%02x,\t/* %u params */\n", nb_args, nb_args );
|
||||||
print_file( file, indent, "0x%02x,\n", pointer_size == 8 ? 10 : 8 );
|
*offset += 6;
|
||||||
print_file( file, indent, "0x%02x,\n", ext_flags );
|
extra_size = 8;
|
||||||
print_file( file, indent, "NdrFcShort(0x0),\n" ); /* server corr hint */
|
|
||||||
print_file( file, indent, "NdrFcShort(0x0),\n" ); /* client corr hint */
|
switch (target.cpu)
|
||||||
print_file( file, indent, "NdrFcShort(0x0),\n" ); /* FIXME: notify index */
|
{
|
||||||
*offset += 14;
|
case CPU_x86_64:
|
||||||
if (pointer_size == 8)
|
|
||||||
{
|
{
|
||||||
unsigned short pos = 0, fpu_mask = 0;
|
unsigned short pos = 0, fpu_mask = 0;
|
||||||
|
|
||||||
|
extra_size += 2;
|
||||||
|
print_file( file, indent, "0x%02x,\n", extra_size );
|
||||||
|
print_file( file, indent, "0x%02x,\n", ext_flags );
|
||||||
|
print_file( file, indent, "NdrFcShort(0x0),\n" ); /* server corr hint */
|
||||||
|
print_file( file, indent, "NdrFcShort(0x0),\n" ); /* client corr hint */
|
||||||
|
print_file( file, indent, "NdrFcShort(0x0),\n" ); /* FIXME: notify index */
|
||||||
if (is_object( iface )) pos += 2;
|
if (is_object( iface )) pos += 2;
|
||||||
if (args) LIST_FOR_EACH_ENTRY( var, args, var_t, entry )
|
if (args) LIST_FOR_EACH_ENTRY( var, args, var_t, entry )
|
||||||
{
|
{
|
||||||
|
@ -1503,8 +1632,40 @@ static void write_proc_func_interp( FILE *file, int indent, const type_t *iface,
|
||||||
if (pos >= 16) break;
|
if (pos >= 16) break;
|
||||||
}
|
}
|
||||||
print_file( file, indent, "NdrFcShort(0x%x),\n", fpu_mask ); /* floating point mask */
|
print_file( file, indent, "NdrFcShort(0x%x),\n", fpu_mask ); /* floating point mask */
|
||||||
*offset += 2;
|
break;
|
||||||
}
|
}
|
||||||
|
case CPU_ARM:
|
||||||
|
case CPU_ARM64:
|
||||||
|
{
|
||||||
|
unsigned int i, len, count = stack_size / pointer_size;
|
||||||
|
unsigned char *params = xmalloc( count );
|
||||||
|
|
||||||
|
count = fill_params_array( iface, func, params, count );
|
||||||
|
len = compress_params_array( params, count );
|
||||||
|
|
||||||
|
extra_size += 3 + len + !(len % 2);
|
||||||
|
print_file( file, indent, "0x%02x,\n", extra_size );
|
||||||
|
print_file( file, indent, "0x%02x,\n", ext_flags );
|
||||||
|
print_file( file, indent, "NdrFcShort(0x0),\n" ); /* server corr hint */
|
||||||
|
print_file( file, indent, "NdrFcShort(0x0),\n" ); /* client corr hint */
|
||||||
|
print_file( file, indent, "NdrFcShort(0x0),\n" ); /* FIXME: notify index */
|
||||||
|
print_file( file, indent, "NdrFcShort(0x%02x),\n", count );
|
||||||
|
print_file( file, indent, "0x%02x,\n", len );
|
||||||
|
for (i = 0; i < len; i++) print_file( file, indent, "0x%02x,\n", params[i] );
|
||||||
|
if (!(len % 2)) print_file( file, indent, "0x00,\n" );
|
||||||
|
free( params );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case CPU_i386:
|
||||||
|
default:
|
||||||
|
print_file( file, indent, "0x%02x,\n", extra_size );
|
||||||
|
print_file( file, indent, "0x%02x,\n", ext_flags );
|
||||||
|
print_file( file, indent, "NdrFcShort(0x0),\n" ); /* server corr hint */
|
||||||
|
print_file( file, indent, "NdrFcShort(0x0),\n" ); /* client corr hint */
|
||||||
|
print_file( file, indent, "NdrFcShort(0x0),\n" ); /* FIXME: notify index */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
*offset += extra_size;
|
||||||
|
|
||||||
/* emit argument data */
|
/* emit argument data */
|
||||||
if (args) LIST_FOR_EACH_ENTRY( var, args, var_t, entry )
|
if (args) LIST_FOR_EACH_ENTRY( var, args, var_t, entry )
|
||||||
|
|
Loading…
Reference in a new issue