mirror of
git://source.winehq.org/git/wine.git
synced 2024-10-14 21:07:17 +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;
|
||||
}
|
||||
|
||||
/* 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,
|
||||
const var_t *func, unsigned int *offset,
|
||||
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_offset = 0;
|
||||
unsigned int stack_align;
|
||||
unsigned int extra_size = 0;
|
||||
unsigned short param_num = 0;
|
||||
unsigned short handle_stack_offset = 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, "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,\n", pointer_size == 8 ? 10 : 8 );
|
||||
*offset += 6;
|
||||
extra_size = 8;
|
||||
|
||||
switch (target.cpu)
|
||||
{
|
||||
case CPU_x86_64:
|
||||
{
|
||||
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 */
|
||||
*offset += 14;
|
||||
if (pointer_size == 8)
|
||||
{
|
||||
unsigned short pos = 0, fpu_mask = 0;
|
||||
|
||||
if (is_object( iface )) pos += 2;
|
||||
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;
|
||||
}
|
||||
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 */
|
||||
if (args) LIST_FOR_EACH_ENTRY( var, args, var_t, entry )
|
||||
|
|
Loading…
Reference in a new issue