fixed global move propagation.

This commit is contained in:
Mphatso Raymond Mataka
2025-01-21 23:42:00 -08:00
parent 1a4551eca5
commit b7c8244daf
17 changed files with 2789 additions and 1044 deletions
+140 -12
View File
@@ -99,6 +99,17 @@ static void assert_valid_binary_float_operation(ir_operation* operation)
assert(ir_operand::is_vector(&operation->sources[0]));
}
static void assert_valid_binary_float_comparison_operation(ir_operation* operation)
{
assert_operand_count(operation, 1, 3);
assert_same_registers(operation->destinations[0], operation->sources[0]);
assert_same_size({operation->destinations[0], operation->sources[0], operation->sources[1]});
assert(ir_operand::is_vector(&operation->sources[0]));
assert_is_constant(operation->sources[2]);
}
void assemble_x86_64_code(void** result_code, uint64_t* result_code_size, ir_operation_block* source_ir)
{
arena_allocator* allocator = source_ir->allocator;
@@ -156,7 +167,7 @@ void assemble_x86_64_code(void** result_code, uint64_t* result_code_size, ir_ope
}; break;
case ir_compare_and_swap:
case x86_cmpxchg:
{
assert_operand_count(&working_operation, 1, 3);
@@ -368,11 +379,8 @@ void assemble_x86_64_code(void** result_code, uint64_t* result_code_size, ir_ope
assert_is_register(destinations[0]);
assert_is_register(sources[0]);
//assert_all_registers(&working_operation);
assert(destinations[0].meta_data == sources[0].meta_data);
assert(destinations[0].meta_data == sources[1].meta_data);
assert_same_size({destinations[0], sources[0], sources[1]});
if (ir_operand::is_constant(&sources[1]))
{
@@ -814,13 +822,26 @@ void assemble_x86_64_code(void** result_code, uint64_t* result_code_size, ir_ope
ir_operand d = working_operation.destinations[0];
ir_operand s0 = working_operation.sources[0];
ir_operand s1 = working_operation.sources[1];
switch (d.meta_data)
{
case int32: c.lea(create_operand<Xbyak::Reg32>(d), c.ptr[create_operand<Xbyak::Reg32>(s0) + create_operand<Xbyak::Reg32>(s1)]); break;
case int64: c.lea(create_operand<Xbyak::Reg64>(d), c.ptr[create_operand<Xbyak::Reg64>(s0) + create_operand<Xbyak::Reg64>(s1)]); break;
default: throw_error();
if (ir_operand::is_constant(&s1))
{
switch (d.meta_data)
{
case int32: c.lea(create_operand<Xbyak::Reg32>(d), c.ptr[create_operand<Xbyak::Reg32>(s0) + s1.value]); break;
case int64: c.lea(create_operand<Xbyak::Reg64>(d), c.ptr[create_operand<Xbyak::Reg64>(s0) + s1.value]); break;
default: throw_error();
}
}
else
{
switch (d.meta_data)
{
case int32: c.lea(create_operand<Xbyak::Reg32>(d), c.ptr[create_operand<Xbyak::Reg32>(s0) + create_operand<Xbyak::Reg32>(s1)]); break;
case int64: c.lea(create_operand<Xbyak::Reg64>(d), c.ptr[create_operand<Xbyak::Reg64>(s0) + create_operand<Xbyak::Reg64>(s1)]); break;
default: throw_error();
}
}
}; break;
@@ -852,6 +873,19 @@ void assemble_x86_64_code(void** result_code, uint64_t* result_code_size, ir_ope
}; break;
case x86_cmpss: assert_valid_binary_float_comparison_operation(&working_operation); c.cmpss(create_operand<Xbyak::Xmm>(working_operation.destinations[0]), create_operand<Xbyak::Xmm>(working_operation.sources[1]), working_operation.sources[2].value); break;
case x86_cmpsd: assert_valid_binary_float_comparison_operation(&working_operation); c.cmpsd(create_operand<Xbyak::Xmm>(working_operation.destinations[0]), create_operand<Xbyak::Xmm>(working_operation.sources[1]), working_operation.sources[2].value); break;
case x86_cmpps: assert_valid_binary_float_comparison_operation(&working_operation); c.cmpps(create_operand<Xbyak::Xmm>(working_operation.destinations[0]), create_operand<Xbyak::Xmm>(working_operation.sources[1]), working_operation.sources[2].value); break;
case x86_cmppd: assert_valid_binary_float_comparison_operation(&working_operation); c.cmppd(create_operand<Xbyak::Xmm>(working_operation.destinations[0]), create_operand<Xbyak::Xmm>(working_operation.sources[1]), working_operation.sources[2].value); break;
case x86_haddpd: assert_valid_binary_float_operation(&working_operation); c.haddpd(create_operand<Xbyak::Xmm>(working_operation.destinations[0]), create_operand<Xbyak::Xmm>(working_operation.sources[1])); break;
case x86_haddps: assert_valid_binary_float_operation(&working_operation); c.haddps(create_operand<Xbyak::Xmm>(working_operation.destinations[0]), create_operand<Xbyak::Xmm>(working_operation.sources[1])); break;
case x86_paddb: assert_valid_binary_float_operation(&working_operation); c.paddb(create_operand<Xbyak::Xmm>(working_operation.destinations[0]), create_operand<Xbyak::Xmm>(working_operation.sources[1])); break;
case x86_paddw: assert_valid_binary_float_operation(&working_operation); c.paddw(create_operand<Xbyak::Xmm>(working_operation.destinations[0]), create_operand<Xbyak::Xmm>(working_operation.sources[1])); break;
case x86_paddd: assert_valid_binary_float_operation(&working_operation); c.paddd(create_operand<Xbyak::Xmm>(working_operation.destinations[0]), create_operand<Xbyak::Xmm>(working_operation.sources[1])); break;
case x86_paddq: assert_valid_binary_float_operation(&working_operation); c.paddq(create_operand<Xbyak::Xmm>(working_operation.destinations[0]), create_operand<Xbyak::Xmm>(working_operation.sources[1])); break;
case x86_addpd: assert_valid_binary_float_operation(&working_operation); c.addpd(create_operand<Xbyak::Xmm>(working_operation.destinations[0]), create_operand<Xbyak::Xmm>(working_operation.sources[1])); break;
case x86_addps: assert_valid_binary_float_operation(&working_operation); c.addps(create_operand<Xbyak::Xmm>(working_operation.destinations[0]), create_operand<Xbyak::Xmm>(working_operation.sources[1])); break;
case x86_addsd: assert_valid_binary_float_operation(&working_operation); c.addsd(create_operand<Xbyak::Xmm>(working_operation.destinations[0]), create_operand<Xbyak::Xmm>(working_operation.sources[1])); break;
@@ -878,9 +912,103 @@ void assemble_x86_64_code(void** result_code, uint64_t* result_code_size, ir_ope
case x86_pand: assert_valid_binary_float_operation(&working_operation); c.pand(create_operand<Xbyak::Xmm>(working_operation.destinations[0]), create_operand<Xbyak::Xmm>(working_operation.sources[1])); break;
case x86_pandn: assert_valid_binary_float_operation(&working_operation); c.pandn(create_operand<Xbyak::Xmm>(working_operation.destinations[0]), create_operand<Xbyak::Xmm>(working_operation.sources[1])); break;
case x86_cvtsd2ss: c.cvtsd2ss(create_operand<Xbyak::Xmm>(working_operation.destinations[0]), create_operand<Xbyak::Xmm>(working_operation.sources[0])); break;
case x86_cvtss2sd: c.cvtss2sd(create_operand<Xbyak::Xmm>(working_operation.destinations[0]), create_operand<Xbyak::Xmm>(working_operation.sources[0])); break;
case x86_sqrtss: c.sqrtss(create_operand<Xbyak::Xmm>(working_operation.destinations[0]), create_operand<Xbyak::Xmm>(working_operation.sources[0])); break;
case x86_sqrtsd: c.sqrtsd(create_operand<Xbyak::Xmm>(working_operation.destinations[0]), create_operand<Xbyak::Xmm>(working_operation.sources[0])); break;
case x86_sqrtps: c.sqrtps(create_operand<Xbyak::Xmm>(working_operation.destinations[0]), create_operand<Xbyak::Xmm>(working_operation.sources[0])); break;
case x86_sqrtpd: c.sqrtpd(create_operand<Xbyak::Xmm>(working_operation.destinations[0]), create_operand<Xbyak::Xmm>(working_operation.sources[0])); break;
case x86_popcnt:
{
ir_operand destination = working_operation.destinations[0];
ir_operand source = working_operation.sources[0];
assert_same_size({destination, source});
switch (destination.meta_data)
{
case int16: c.popcnt(create_operand<Xbyak::Reg16>(destination), create_operand<Xbyak::Reg16>(source)); break;
case int32: c.popcnt(create_operand<Xbyak::Reg32>(destination), create_operand<Xbyak::Reg32>(source)); break;
case int64: c.popcnt(create_operand<Xbyak::Reg64>(destination), create_operand<Xbyak::Reg64>(source)); break;
default: throw_error();
}
}; break;
case x86_lzcnt:
{
ir_operand destination = working_operation.destinations[0];
ir_operand source = working_operation.sources[0];
assert_same_size({destination, source});
switch (destination.meta_data)
{
case int32: c.lzcnt(create_operand<Xbyak::Reg32>(destination), create_operand<Xbyak::Reg32>(source)); break;
case int64: c.lzcnt(create_operand<Xbyak::Reg64>(destination), create_operand<Xbyak::Reg64>(source)); break;
default: throw_error();
}
} break;
case x86_add_flags:
case x86_sub_flags:
{
ir_operand* destinations = working_operation.destinations.data;
ir_operand* sources = working_operation.sources.data;
assert_is_register(destinations[0]);
assert_same_registers(destinations[0], sources[0]);
assert(ir_operand::is_register(&destinations[0]));
assert(ir_operand::is_register(&sources[0]));
Xbyak::Operand dn = create_operand(destinations[0]);
assert_operand_count(&working_operation, 5, 2);
if (ir_operand::is_constant(&sources[1]))
{
uint64_t imm = sources[1].value;
if (imm >= INT32_MAX)
{
throw_error();
}
switch (instruction)
{
case x86_add_flags: c.add(dn, imm); break;
case x86_sub_flags: c.sub(dn, imm); break;
default: throw_error();
}
}
else
{
assert(destinations[0].value == sources[0].value);
assert(destinations[0].meta_data == sources[0].meta_data);
assert(destinations[0].meta_data == sources[1].meta_data);
Xbyak::Operand m = create_operand(sources[1]);
switch (instruction)
{
case x86_add_flags: c.add(dn, m); break;
case x86_sub_flags: c.sub(dn, m); break;
default: throw_error();
}
}
c.sets(create_operand<Xbyak::Reg8>(destinations[1]));
c.sete(create_operand<Xbyak::Reg8>(destinations[2]));
c.setc(create_operand<Xbyak::Reg8>(destinations[3]));
c.seto(create_operand<Xbyak::Reg8>(destinations[4]));
for (int i = 1; i < 5; ++i)
{
c.and_(create_operand<Xbyak::Reg64>(destinations[i]), 1);
}
}; break;
case ir_floating_point_compare_equal:
case ir_floating_point_compare_less:
+7
View File
@@ -7,6 +7,8 @@
#include "ir/basic_register_allocator.h"
#include "ir/undefined_behavior_check.h"
#include <iostream>
void assemble_x86_64_pipeline(void** result_code, uint64_t* result_code_size, ir_operation_block* source_ir, bool optimize, abi working_abi, compiler_flags flags)
{
arena_allocator* allocator = source_ir->allocator;
@@ -33,6 +35,11 @@ void assemble_x86_64_pipeline(void** result_code, uint64_t* result_code_size, ir
if (flags & optimize_ssa)
{
ssa_construct_and_optimize(source_ir, flags);
if (flags & mathmatical_fold)
{
ir_operation_block::log(source_ir);
}
}
x86_pre_allocator_context::run_pass(&pre_allocation_data, pre_allocated_code, source_ir, working_abi.cpu,working_abi.os);
+267 -37
View File
@@ -189,6 +189,9 @@ static bool instruction_is_commutative(uint64_t instruction)
case x86_mulpd:
case x86_mulss:
case x86_mulsd:
case x86_add_flags:
case ir_compare_equal:
case ir_compare_not_equal:
{
return true;
};
@@ -205,7 +208,7 @@ static void swap(ir_operand* l, ir_operand* r)
*r = tmp;
}
static void emit_d_n_f_d_n_m(x86_pre_allocator_context* result, ir_instructions instruction, ir_operand destination, ir_operand source_0, ir_operand source_1)
static void emit_d_n_f_d_n_m(x86_pre_allocator_context* result, ir_instructions instruction, ir_operand destination, ir_operand source_0, ir_operand source_1, ir_operation* source_operation)
{
assert_same_size({ destination, source_0, source_1 });
@@ -214,48 +217,113 @@ static void emit_d_n_f_d_n_m(x86_pre_allocator_context* result, ir_instructions
swap(&source_0, &source_1);
}
if (instruction_is_commutative(instruction) && ir_operand::are_equal(destination, source_1) && !ir_operand::are_equal(destination, source_0))
{
swap(&source_0, &source_1);
}
intrusive_linked_list_element<ir_operation>* core_operation = nullptr;
if ((ir_operand::is_constant(&source_1) && source_1.value < INT32_MAX) && !ir_operand::is_constant(&source_0) && instruction != ir_multiply)
{
if (instruction == ir_add && ir_operand::get_raw_size(&destination) > int16)
{
ir_operation_block::emitds(result->ir, x86_lea, destination, source_0, source_1);
return;
}
if (!ir_operand::are_equal(destination, source_0))
{
emit_move(result,destination, source_0);
}
ir_operation_block::emitds(result->ir, instruction, destination, destination, source_1);
return;
}
ir_operand working_destination = destination;
ir_operand working_source_0 = register_or_constant(result, &source_0);
ir_operand working_source_1 = register_or_constant(result, &source_1);
if (instruction_is_commutative(instruction) && ir_operand::are_equal(working_destination, working_source_1) && !ir_operand::are_equal(working_destination, working_source_0))
{
swap(&source_0, &source_1);
}
if (ir_operand::are_equal(working_destination, working_source_0))
{
ir_operation_block::emitds(result->ir, instruction, working_destination, working_destination, working_source_1);
}
else if (instruction == ir_add && ir_operand::get_raw_size(&working_destination) > int16)
{
ir_operation_block::emitds(result->ir, x86_lea, working_destination, working_source_0, working_source_1);
}
else if (!ir_operand::are_equal(working_destination, working_source_1))
{
emit_move(result,destination, source_0);
ir_operation_block::emitds(result->ir, instruction, working_destination, working_destination, working_source_1);
core_operation = ir_operation_block::emitds(result->ir, instruction, destination, destination, source_1);
}
else
{
ir_operand working_scrap = create_scrap_operand(result, destination.meta_data);
ir_operand working_destination = destination;
ir_operand working_source_0 = register_or_constant(result, &source_0);
ir_operand working_source_1 = register_or_constant(result, &source_1);
emit_move(result, working_scrap, working_source_0);
ir_operation_block::emitds(result->ir, instruction, working_scrap, working_scrap, working_source_1);
emit_move(result, working_destination, working_scrap);
if (ir_operand::are_equal(working_destination, working_source_0))
{
core_operation = ir_operation_block::emitds(result->ir, instruction, working_destination, working_destination, working_source_1);
}
else if (instruction == ir_add && ir_operand::get_raw_size(&working_destination) > int16)
{
ir_operation_block::emitds(result->ir, x86_lea, working_destination, working_source_0, working_source_1);
}
else if (!ir_operand::are_equal(working_destination, working_source_1))
{
emit_move(result,destination, source_0);
core_operation = ir_operation_block::emitds(result->ir, instruction, working_destination, working_destination, working_source_1);
}
else
{
ir_operand working_scrap = create_scrap_operand(result, destination.meta_data);
emit_move(result, working_scrap, working_source_0);
core_operation = ir_operation_block::emitds(result->ir, instruction, working_scrap, working_scrap, working_source_1);
emit_move(result, working_destination, working_scrap);
}
}
switch (instruction)
{
case x86_add_flags:
case x86_sub_flags:
{
if (core_operation == nullptr)
{
throw_error();
}
ir_operand new_destinations[5];
ir_operand* new_sources = core_operation->data.sources.data;
new_destinations[0] = core_operation->data.destinations[0];
for (int i = 1; i < 5; ++i)
{
new_destinations[i] = source_operation->destinations[i];
}
ir_operation_block::emit_with(result->ir, instruction, new_destinations, 5, new_sources, 2, core_operation);
core_operation->data.instruction = ir_no_operation;
core_operation->data.sources.count = 0;
core_operation->data.destinations.count = 0;
}; break;
case x86_cmpss:
case x86_cmpsd:
case x86_cmpps:
case x86_cmppd:
{
if (core_operation == nullptr)
{
throw_error();
}
ir_operand sources_with_control[3];
for (int i = 0; i < 2; ++i)
{
sources_with_control[i] = core_operation->data.sources[i];
}
sources_with_control[2] = source_operation->sources[2];
assert_is_constant(sources_with_control[2]);
ir_operation_block::emit_with(result->ir, instruction, core_operation->data.destinations.data, 1, sources_with_control, 3, core_operation);
core_operation->data.instruction = ir_no_operation;
core_operation->data.sources.count = 0;
core_operation->data.destinations.count = 0;
}; break;
}
}
@@ -327,10 +395,24 @@ static void emit_compare(x86_pre_allocator_context* result, uint64_t instruction
{
assert_same_size({ destination, source_0, source_1 });
if (ir_operand::is_constant(&source_0) && !ir_operand::is_constant(&source_1) && instruction_is_commutative(instruction))
{
swap(&source_0, &source_1);
}
ir_operand working_destination = destination;
ir_operand working_source_0 = register_or_constant(result, &source_0);
ir_operand working_source_1 = register_or_constant(result, &source_1);
ir_operand working_source_1;
if (ir_operand::is_constant(&source_1) && source_1.value < INT32_MAX)
{
working_source_1 = source_1;
}
else
{
working_source_1 = register_or_constant(result, &source_1);
}
ir_operation_block::emitds(result->ir, instruction, working_destination, working_source_0, working_source_1);
}
@@ -679,7 +761,7 @@ static void emit_compare_and_swap(x86_pre_allocator_context* result, ir_operatio
ir_operand rax = RAX(expecting.meta_data);
emit_move(result, rax, expecting);
ir_operation_block::emitds(result->ir, ir_compare_and_swap, destination, address, rax, to_swap);
ir_operation_block::emitds(result->ir, x86_cmpxchg, destination, address, rax, to_swap);
ir_operation_block::emits(result->ir, ir_instructions::ir_register_allocator_p_unlock, RAX(int64));
}
@@ -843,6 +925,91 @@ static void emit_shuf(x86_pre_allocator_context* result, ir_operation* operation
emit_move(result, destination, working);
}
static void emit_store(x86_pre_allocator_context* result, ir_operation* operation)
{
ir_operand source_temp[3];
ir_operation_block* ir = result->ir;
for (int i = 0; i < operation->sources.count; ++i)
{
ir_operand working = operation->sources[i];
if (ir_operand::is_constant(&working) && working.value > INT32_MAX)
{
working = register_or_constant(result, working);
}
source_temp[i] = working;
}
if (operation->sources.count == 3)
{
if (ir_operand::is_constant(&operation->sources[0]) && !ir_operand::is_constant(&operation->sources[1]))
{
swap(&source_temp[0], &source_temp[1]);
}
}
if (ir_operand::is_constant(&source_temp[0]))
{
source_temp[0] = register_or_constant(result, source_temp[0]);
}
int last = operation->sources.count - 1;
if (ir_operand::is_constant(&source_temp[last]))
{
source_temp[last] = register_or_constant(result, source_temp[last]);
}
ir_operation_block::emit_with(
ir,
operation->instruction,
operation->destinations.data, operation->destinations.count,
source_temp, operation->sources.count
);
}
static void emit_load(x86_pre_allocator_context* result, ir_operation* operation)
{
ir_operation_block* ir = result->ir;
ir_operand source_temp[2];
for (int i = 0; i < operation->sources.count; ++i)
{
ir_operand working = operation->sources[i];
if (ir_operand::is_constant(&working) && working.value > INT32_MAX)
{
working = register_or_constant(result, working);
}
source_temp[i] = working;
}
if (operation->sources.count == 2)
{
if (ir_operand::is_constant(&operation->sources[0]) && !ir_operand::is_constant(&operation->sources[1]))
{
swap(&source_temp[0], &source_temp[1]);
}
}
if (ir_operand::is_constant(&source_temp[0]))
{
source_temp[0] = register_or_constant(result, source_temp[0]);
}
ir_operation_block::emit_with(
ir,
operation->instruction,
operation->destinations.data, operation->destinations.count,
source_temp, operation->sources.count
);
}
static void emit_pre_allocation_instruction(x86_pre_allocator_context* pre_allocator_context, ir_operation* operation, os_information os)
{
ir_instructions working_instruction = (ir_instructions)operation->instruction;
@@ -876,18 +1043,46 @@ static void emit_pre_allocation_instruction(x86_pre_allocator_context* pre_alloc
case x86_subps:
case x86_subsd:
case x86_subss:
case x86_paddb:
case x86_paddw:
case x86_paddd:
case x86_paddq:
case x86_xorps:
case x86_pand:
case x86_orps:
case x86_pandn:
case x86_haddpd:
case x86_haddps:
{
assert_operand_count(operation, 1, 2);
assert_is_register(operation->destinations[0]);
emit_d_n_f_d_n_m(pre_allocator_context, operation->instruction, operation->destinations[0], operation->sources[0], operation->sources[1]);
emit_d_n_f_d_n_m(pre_allocator_context, operation->instruction, operation->destinations[0], operation->sources[0], operation->sources[1], nullptr);
}; break;
case x86_cmpss:
case x86_cmpsd:
case x86_cmpps:
case x86_cmppd:
{
assert_operand_count(operation, 1, 3);
assert_is_register(operation->destinations[0]);
emit_d_n_f_d_n_m(pre_allocator_context, operation->instruction, operation->destinations[0], operation->sources[0], operation->sources[1], operation);
}; break;
case x86_add_flags:
case x86_sub_flags:
{
assert_operand_count(operation, 5, 2);
assert_is_register(operation->destinations[0]);
emit_d_n_f_d_n_m(pre_allocator_context, operation->instruction, operation->destinations[0], operation->sources[0], operation->sources[1], operation);
}; break;
case ir_floating_point_add:
case ir_floating_point_subtract:
case ir_floating_point_multiply:
@@ -1036,11 +1231,26 @@ static void emit_pre_allocation_instruction(x86_pre_allocator_context* pre_alloc
}; break;
case ir_load:
{
emit_load(pre_allocator_context, operation);
}; break;
case ir_store:
{
emit_store(pre_allocator_context, operation);
}; break;
case ir_jump_if:
case ir_vector_zero:
case ir_vector_one:
case x86_roundss:
case x86_roundsd:
case x86_cvtsd2ss:
case x86_cvtss2sd:
case x86_sqrtps:
case x86_sqrtpd:
case x86_sqrtss:
case x86_sqrtsd:
{
emit_as_is(pre_allocator_context, operation);
}; break;
@@ -1053,7 +1263,9 @@ static void emit_pre_allocation_instruction(x86_pre_allocator_context* pre_alloc
case ir_assert_false:
case ir_assert_true:
case ir_store: //TODO this can be optimized
case x86_lzcnt:
case x86_popcnt:
{
emit_with_possible_remaps(pre_allocator_context, operation);
}; break;
@@ -1097,7 +1309,7 @@ static void emit_pre_allocation_instruction(x86_pre_allocator_context* pre_alloc
emit_external_call(pre_allocator_context, operation, os);
}; break;
case ir_compare_and_swap:
case x86_cmpxchg:
{
emit_compare_and_swap(pre_allocator_context, operation);
}; break;
@@ -1119,6 +1331,24 @@ static void emit_pre_allocation_instruction(x86_pre_allocator_context* pre_alloc
throw_error();
}
switch (operation->instruction)
{
case ir_compare_equal:
case ir_compare_greater_equal_signed:
case ir_compare_greater_equal_unsigned:
case ir_compare_greater_signed:
case ir_compare_greater_unsigned:
case ir_compare_less_equal_signed:
case ir_compare_less_equal_unsigned:
case ir_compare_less_signed:
case ir_compare_less_unsigned:
case ir_compare_not_equal:
return;
default:
break;
}
for (int i = 0; i < operation->destinations.count; ++i)
{
ir_operand destination = operation->destinations[i];
@@ -205,4 +205,14 @@ uint64_t use_fast_float_interpreter(interpreter_data* ctx)
uint64_t use_x86_sse41_interpreter(interpreter_data* ctx)
{
return true;
}
uint64_t use_x86_interpreter(interpreter_data* ctx)
{
return false;
}
uint64_t use_x86_lzcnt_interpreter(interpreter_data* ctx)
{
return false;
}
@@ -235,6 +235,60 @@ uint64_t use_x86_sse41_jit(ssa_emit_context* ctx)
return 1;
}
uint64_t use_x86_jit(ssa_emit_context* ctx)
{
return 1;
}
uint64_t use_x86_lzcnt_jit(ssa_emit_context* ctx)
{
return 1;
}
static ir_operand x86_add_subtract_set_flags_jit(ssa_emit_context* ctx,uint64_t O, ir_operand n, ir_operand m, bool is_add)
{
aarch64_emit_context* actx = (aarch64_emit_context*)ctx->context_data;
aarch64_context_offsets offsets = actx->process->guest_context_offset_data;
ir_operand result = ssa_emit_context::create_local(ctx, O);
ir_operand destinations[] =
{
result,
aarch64_emit_context::get_context_reg_raw(actx, offsets.n_offset),
aarch64_emit_context::get_context_reg_raw(actx, offsets.z_offset),
aarch64_emit_context::get_context_reg_raw(actx, offsets.c_offset),
aarch64_emit_context::get_context_reg_raw(actx, offsets.v_offset),
};
ir_operand sources[] =
{
n,
m
};
ir_operation_block::emit_with(ctx->ir, is_add ? x86_add_flags : x86_sub_flags, destinations, 5, sources, 2);
if (!is_add)
{
ir_operand c = aarch64_emit_context::get_context_reg_raw(actx, offsets.c_offset);
ir_operation_block::emitds(ctx->ir, ir_bitwise_exclusive_or, c, c, ir_operand::create_con(1, c.meta_data));
}
return result;
}
ir_operand x86_add_set_flags_jit(ssa_emit_context* ctx,uint64_t O, ir_operand n, ir_operand m)
{
return x86_add_subtract_set_flags_jit(ctx, O, n, m, true);
}
ir_operand x86_subtract_set_flags_jit(ssa_emit_context* ctx,uint64_t O, ir_operand n, ir_operand m)
{
return x86_add_subtract_set_flags_jit(ctx, O, n, m, false);
}
ir_operand intrinsic_unary_jit(ssa_emit_context* ctx,uint64_t R, uint64_t instruction, ir_operand source)
{
return ssa_emit_context::emit_ssa(ctx, (ir_instructions)instruction, source, R);
@@ -253,4 +307,9 @@ ir_operand intrinsic_binary_imm_jit(ssa_emit_context* ctx,uint64_t R, uint64_t i
ir_operand intrinsic_ternary_imm_jit(ssa_emit_context* ctx,uint64_t R, uint64_t instruction, ir_operand source_0, ir_operand source_1, uint64_t source_2)
{
return ssa_emit_context::emit_ssa(ctx, (ir_instructions)instruction, source_0, source_1, ir_operand::create_con(source_2));
}
ir_operand intrinsic_ternary_jit(ssa_emit_context* ctx,uint64_t R, uint64_t instruction, ir_operand source_0, ir_operand source_1, ir_operand source_2)
{
return ssa_emit_context::emit_ssa(ctx, (ir_instructions)instruction, source_0, source_1, source_2);
}
File diff suppressed because it is too large Load Diff
+42 -14
View File
@@ -115,8 +115,10 @@ template <typename O>
O add_subtract_carry_impl_interpreter(interpreter_data* ctx, O n, O m, uint64_t set_flags, uint64_t is_add, O carry);
uint8_t condition_holds_interpreter(interpreter_data* ctx, uint64_t cond);
void branch_long_universal_interpreter(interpreter_data* ctx, uint64_t Rn, uint64_t link);
uint64_t select_interpreter(interpreter_data* ctx, uint64_t condition, uint64_t yes, uint64_t no);
uint64_t create_mask_interpreter(interpreter_data* ctx, uint64_t bits);
uint64_t shift_left_check_interpreter(interpreter_data* ctx, uint64_t to_shift, uint64_t shift, uint64_t size);
uint64_t get_x86_rounding_mode_interpreter(interpreter_data* ctx, uint64_t rounding);
uint64_t shift_right_check_interpreter(interpreter_data* ctx, uint64_t to_shift, uint64_t shift, uint64_t size, uint64_t is_unsigned);
uint64_t reverse_interpreter(interpreter_data* ctx, uint128_t word, uint64_t M, uint64_t N);
void convert_to_int_interpreter(interpreter_data* ctx, uint64_t sf, uint64_t ftype, uint64_t Rd, uint64_t Rn, uint64_t round, uint64_t is_unsigned, uint64_t to_vector);
@@ -134,7 +136,6 @@ void convert_to_float_interpreter(interpreter_data* ctx, uint64_t sf, uint64_t f
uint128_t replicate_vector_interpreter(interpreter_data* ctx, uint128_t source, uint64_t v_size, uint64_t count);
void st_interpreter(interpreter_data* ctx, uint64_t wback, uint64_t Q, uint64_t L, uint64_t opcode, uint64_t size, uint64_t Rm, uint64_t Rn, uint64_t Rt);
void memory_1_interpreter(interpreter_data* ctx, uint64_t wback, uint64_t Q, uint64_t L, uint64_t R, uint64_t Rm, uint64_t o2, uint64_t opcode, uint64_t S, uint64_t size, uint64_t Rn, uint64_t Rt, uint64_t is_load);
void fcm_vector_interpreter(interpreter_data* ctx, uint64_t Rd, uint64_t Rn, uint64_t Rm, uint64_t mode, uint64_t Q, uint64_t sz);
uint64_t bits_r_interpreter(interpreter_data* ctx, uint64_t operand, uint64_t top, uint64_t bottom);
uint64_t infinity_interpreter(interpreter_data* ctx, uint64_t sign, uint64_t N);
uint64_t float_is_nan_interpreter(interpreter_data* ctx, uint64_t operand, uint64_t N);
@@ -176,6 +177,12 @@ void intrinsic_float_binary_scalar_interpreter(interpreter_data* ctx, uint64_t R
void x86_sse_logic_vector_interpreter(interpreter_data* ctx, uint64_t Rd, uint64_t Rn, uint64_t Rm, uint64_t Q, uint64_t invert, uint64_t primary_instruction);
uint128_t sse_copy_to_xmm_from_xmm_element_interpreter(interpreter_data* ctx, uint128_t source, uint64_t size, uint64_t index);
uint128_t sse_coppy_gp_across_lanes_interpreter(interpreter_data* ctx, uint64_t source, uint64_t size);
void floating_point_multiply_scalar_element_interpreter(interpreter_data* ctx, uint64_t Rd, uint64_t Rn, uint64_t Rm, uint64_t sz, uint64_t index);
void floating_point_multiply_vector_element_interpreter(interpreter_data* ctx, uint64_t Q, uint64_t Rd, uint64_t Rn, uint64_t Rm, uint64_t sz, uint64_t index);
void floating_point_multiply_accumulate_scalar_element_interpreter(interpreter_data* ctx, uint64_t Rd, uint64_t Rn, uint64_t Rm, uint64_t neg, uint64_t sz, uint64_t index);
void floating_point_multiply_accumulate_vector_element_interpreter(interpreter_data* ctx, uint64_t Q, uint64_t Rd, uint64_t Rn, uint64_t Rm, uint64_t neg, uint64_t sz, uint64_t index);
void fcm_vector_interpreter(interpreter_data* ctx, uint64_t Rd, uint64_t Rn, uint64_t Rm, uint64_t mode, uint64_t Q, uint64_t sz);
uint128_t clear_vector_scalar_interpreter(interpreter_data* ctx, uint128_t working, uint64_t fltsize);
void add_subtract_imm12_interpreter(interpreter_data* ctx, uint64_t sf, uint64_t op, uint64_t S, uint64_t sh, uint64_t imm12, uint64_t Rn, uint64_t Rd);
void add_subtract_shifted_interpreter(interpreter_data* ctx, uint64_t sf, uint64_t op, uint64_t S, uint64_t shift, uint64_t Rm, uint64_t imm6, uint64_t Rn, uint64_t Rd);
void add_subtract_extended_interpreter(interpreter_data* ctx, uint64_t sf, uint64_t op, uint64_t S, uint64_t Rm, uint64_t option, uint64_t imm3, uint64_t Rn, uint64_t Rd);
@@ -185,6 +192,7 @@ void multiply_with_32_interpreter(interpreter_data* ctx, uint64_t U, uint64_t Rm
void multiply_hi_interpreter(interpreter_data* ctx, uint64_t U, uint64_t Rm, uint64_t o0, uint64_t Rn, uint64_t Rd);
void multiply_additive_interpreter(interpreter_data* ctx, uint64_t sf, uint64_t Rm, uint64_t o0, uint64_t Ra, uint64_t Rn, uint64_t Rd);
void divide_interpreter(interpreter_data* ctx, uint64_t sf, uint64_t Rm, uint64_t o1, uint64_t Rn, uint64_t Rd);
uint64_t create_rbit_mask_interpreter(interpreter_data* ctx, uint64_t index);
void rbit_interpreter(interpreter_data* ctx, uint64_t sf, uint64_t Rn, uint64_t Rd);
void rev16_interpreter(interpreter_data* ctx, uint64_t sf, uint64_t Rn, uint64_t Rd);
void reverse_interpreter(interpreter_data* ctx, uint64_t sf, uint64_t opc, uint64_t Rn, uint64_t Rd);
@@ -220,6 +228,7 @@ void load_store_register_imm_unsigned_interpreter(interpreter_data* ctx, uint64_
void load_store_register_imm_unscaled_interpreter(interpreter_data* ctx, uint64_t size, uint64_t VR, uint64_t opc, uint64_t imm9, uint64_t wb, uint64_t Rn, uint64_t Rt);
void load_store_register_offset_interpreter(interpreter_data* ctx, uint64_t size, uint64_t VR, uint64_t opc, uint64_t Rm, uint64_t option, uint64_t S, uint64_t Rn, uint64_t Rt);
void load_store_exclusive_ordered_interpreter(interpreter_data* ctx, uint64_t size, uint64_t ordered, uint64_t L, uint64_t Rs, uint64_t o0, uint64_t Rn, uint64_t Rt);
uint64_t exclusive_address_mask_interpreter(interpreter_data* ctx);
void load_exclusive_interpreter(interpreter_data* ctx, uint64_t is_exclusive, uint64_t size, uint64_t Rn, uint64_t Rt);
void store_exclusive_interpreter(interpreter_data* ctx, uint64_t is_exclusive, uint64_t size, uint64_t Rn, uint64_t Rt, uint64_t Rs);
void conversion_between_floating_point_and_fixed_point_interpreter(interpreter_data* ctx, uint64_t sf, uint64_t S, uint64_t ftype, uint64_t rmode, uint64_t opcode, uint64_t scale, uint64_t Rn, uint64_t Rd);
@@ -245,6 +254,12 @@ void fmul_vector_by_element_interpreter(interpreter_data* ctx, uint64_t Q, uint6
void fmul_accumulate_scalar_interpreter(interpreter_data* ctx, uint64_t sz, uint64_t L, uint64_t M, uint64_t Rm, uint64_t neg, uint64_t H, uint64_t Rn, uint64_t Rd);
void fmul_accumulate_element_interpreter(interpreter_data* ctx, uint64_t Q, uint64_t sz, uint64_t L, uint64_t M, uint64_t Rm, uint64_t neg, uint64_t H, uint64_t Rn, uint64_t Rd);
void faddp_scalar_interpreter(interpreter_data* ctx, uint64_t sz, uint64_t Rn, uint64_t Rd);
void fcmeq_vector_zero_interpreter(interpreter_data* ctx, uint64_t Q, uint64_t sz, uint64_t Rn, uint64_t Rd);
void fcmgt_vector_zero_interpreter(interpreter_data* ctx, uint64_t Q, uint64_t sz, uint64_t Rn, uint64_t Rd);
void fcmge_vector_zero_interpreter(interpreter_data* ctx, uint64_t Q, uint64_t sz, uint64_t Rn, uint64_t Rd);
void fcmeq_vector_register_interpreter(interpreter_data* ctx, uint64_t Q, uint64_t sz, uint64_t Rm, uint64_t Rn, uint64_t Rd);
void fcmgt_vector_register_interpreter(interpreter_data* ctx, uint64_t Q, uint64_t sz, uint64_t Rm, uint64_t Rn, uint64_t Rd);
void fcmge_vector_register_interpreter(interpreter_data* ctx, uint64_t Q, uint64_t sz, uint64_t Rm, uint64_t Rn, uint64_t Rd);
void fadd_scalar_interpreter(interpreter_data* ctx, uint64_t ftype, uint64_t Rm, uint64_t Rn, uint64_t Rd);
void fsub_scalar_interpreter(interpreter_data* ctx, uint64_t ftype, uint64_t Rm, uint64_t Rn, uint64_t Rd);
void fmul_scalar_interpreter(interpreter_data* ctx, uint64_t ftype, uint64_t Rm, uint64_t Rn, uint64_t Rd);
@@ -315,12 +330,6 @@ void st2_multiple_structures_no_offset_interpreter(interpreter_data* ctx, uint64
void st2_multiple_structures_post_index_interpreter(interpreter_data* ctx, uint64_t Q, uint64_t Rm, uint64_t size, uint64_t Rn, uint64_t Rt);
void st1_single_structure_no_offset_interpreter(interpreter_data* ctx, uint64_t Q, uint64_t opcode, uint64_t S, uint64_t size, uint64_t Rn, uint64_t Rt);
void st1_single_structure_post_index_interpreter(interpreter_data* ctx, uint64_t Q, uint64_t Rm, uint64_t opcode, uint64_t S, uint64_t size, uint64_t Rn, uint64_t Rt);
void fcmeq_vector_zero_interpreter(interpreter_data* ctx, uint64_t Q, uint64_t sz, uint64_t Rn, uint64_t Rd);
void fcmgt_vector_zero_interpreter(interpreter_data* ctx, uint64_t Q, uint64_t sz, uint64_t Rn, uint64_t Rd);
void fcmge_vector_zero_interpreter(interpreter_data* ctx, uint64_t Q, uint64_t sz, uint64_t Rn, uint64_t Rd);
void fcmeq_vector_register_interpreter(interpreter_data* ctx, uint64_t Q, uint64_t sz, uint64_t Rm, uint64_t Rn, uint64_t Rd);
void fcmgt_vector_register_interpreter(interpreter_data* ctx, uint64_t Q, uint64_t sz, uint64_t Rm, uint64_t Rn, uint64_t Rd);
void fcmge_vector_register_interpreter(interpreter_data* ctx, uint64_t Q, uint64_t sz, uint64_t Rm, uint64_t Rn, uint64_t Rd);
void floating_point_conditional_select_interpreter(interpreter_data* ctx, uint64_t ftype, uint64_t Rm, uint64_t cond, uint64_t Rn, uint64_t Rd);
void fcmp_interpreter(interpreter_data* ctx, uint64_t ftype, uint64_t Rm, uint64_t Rn, uint64_t opc);
void fccmp_interpreter(interpreter_data* ctx, uint64_t ftype, uint64_t Rm, uint64_t cond, uint64_t Rn, uint64_t nzcv);
@@ -340,6 +349,12 @@ uint64_t use_fast_float_interpreter(interpreter_data* ctx);//THIS FUNCTION IS US
uint64_t use_x86_sse_interpreter(interpreter_data* ctx);//THIS FUNCTION IS USER DEFINED
uint64_t use_x86_sse2_interpreter(interpreter_data* ctx);//THIS FUNCTION IS USER DEFINED
uint64_t use_x86_sse41_interpreter(interpreter_data* ctx);//THIS FUNCTION IS USER DEFINED
uint64_t use_x86_interpreter(interpreter_data* ctx);//THIS FUNCTION IS USER DEFINED
uint64_t use_x86_lzcnt_interpreter(interpreter_data* ctx);//THIS FUNCTION IS USER DEFINED
template <typename O>
O x86_add_set_flags_interpreter(interpreter_data* ctx, O n, O m);//THIS FUNCTION IS USER DEFINED
template <typename O>
O x86_subtract_set_flags_interpreter(interpreter_data* ctx, O n, O m);//THIS FUNCTION IS USER DEFINED
uint64_t _get_pc_interpreter(interpreter_data* ctx);//THIS FUNCTION IS USER DEFINED
uint64_t translate_address_interpreter(interpreter_data* ctx, uint64_t address);//THIS FUNCTION IS USER DEFINED
void call_supervisor_interpreter(interpreter_data* ctx, uint64_t svc);//THIS FUNCTION IS USER DEFINED
@@ -376,8 +391,10 @@ ir_operand add_subtract_impl_jit(ssa_emit_context* ctx,uint64_t O, ir_operand n,
ir_operand add_subtract_carry_impl_jit(ssa_emit_context* ctx,uint64_t O, ir_operand n, ir_operand m, uint64_t set_flags, uint64_t is_add, ir_operand carry);
ir_operand condition_holds_jit(ssa_emit_context* ctx, uint64_t cond);
void branch_long_universal_jit(ssa_emit_context* ctx, uint64_t Rn, uint64_t link);
uint64_t select_jit(ssa_emit_context* ctx, uint64_t condition, uint64_t yes, uint64_t no);
ir_operand create_mask_jit(ssa_emit_context* ctx, uint64_t bits);
ir_operand shift_left_check_jit(ssa_emit_context* ctx, ir_operand to_shift, ir_operand shift, uint64_t size);
uint64_t get_x86_rounding_mode_jit(ssa_emit_context* ctx, uint64_t rounding);
ir_operand shift_right_check_jit(ssa_emit_context* ctx, ir_operand to_shift, ir_operand shift, uint64_t size, uint64_t is_unsigned);
ir_operand reverse_jit(ssa_emit_context* ctx, ir_operand word, uint64_t M, uint64_t N);
void convert_to_int_jit(ssa_emit_context* ctx, uint64_t sf, uint64_t ftype, uint64_t Rd, uint64_t Rn, uint64_t round, uint64_t is_unsigned, uint64_t to_vector);
@@ -395,7 +412,6 @@ void convert_to_float_jit(ssa_emit_context* ctx, uint64_t sf, uint64_t ftype, ui
ir_operand replicate_vector_jit(ssa_emit_context* ctx, ir_operand source, uint64_t v_size, uint64_t count);
void st_jit(ssa_emit_context* ctx, uint64_t wback, uint64_t Q, uint64_t L, uint64_t opcode, uint64_t size, uint64_t Rm, uint64_t Rn, uint64_t Rt);
void memory_1_jit(ssa_emit_context* ctx, uint64_t wback, uint64_t Q, uint64_t L, uint64_t R, uint64_t Rm, uint64_t o2, uint64_t opcode, uint64_t S, uint64_t size, uint64_t Rn, uint64_t Rt, uint64_t is_load);
void fcm_vector_jit(ssa_emit_context* ctx, uint64_t Rd, uint64_t Rn, uint64_t Rm, uint64_t mode, uint64_t Q, uint64_t sz);
ir_operand bits_r_jit(ssa_emit_context* ctx, ir_operand operand, uint64_t top, uint64_t bottom);
ir_operand infinity_jit(ssa_emit_context* ctx, uint64_t sign, uint64_t N);
ir_operand float_is_nan_jit(ssa_emit_context* ctx, ir_operand operand, uint64_t N);
@@ -436,6 +452,12 @@ void intrinsic_float_binary_scalar_jit(ssa_emit_context* ctx, uint64_t Rd, uint6
void x86_sse_logic_vector_jit(ssa_emit_context* ctx, uint64_t Rd, uint64_t Rn, uint64_t Rm, uint64_t Q, uint64_t invert, uint64_t primary_instruction);
ir_operand sse_copy_to_xmm_from_xmm_element_jit(ssa_emit_context* ctx, ir_operand source, uint64_t size, uint64_t index);
ir_operand sse_coppy_gp_across_lanes_jit(ssa_emit_context* ctx, ir_operand source, uint64_t size);
void floating_point_multiply_scalar_element_jit(ssa_emit_context* ctx, uint64_t Rd, uint64_t Rn, uint64_t Rm, uint64_t sz, uint64_t index);
void floating_point_multiply_vector_element_jit(ssa_emit_context* ctx, uint64_t Q, uint64_t Rd, uint64_t Rn, uint64_t Rm, uint64_t sz, uint64_t index);
void floating_point_multiply_accumulate_scalar_element_jit(ssa_emit_context* ctx, uint64_t Rd, uint64_t Rn, uint64_t Rm, uint64_t neg, uint64_t sz, uint64_t index);
void floating_point_multiply_accumulate_vector_element_jit(ssa_emit_context* ctx, uint64_t Q, uint64_t Rd, uint64_t Rn, uint64_t Rm, uint64_t neg, uint64_t sz, uint64_t index);
void fcm_vector_jit(ssa_emit_context* ctx, uint64_t Rd, uint64_t Rn, uint64_t Rm, uint64_t mode, uint64_t Q, uint64_t sz);
ir_operand clear_vector_scalar_jit(ssa_emit_context* ctx, ir_operand working, uint64_t fltsize);
void add_subtract_imm12_jit(ssa_emit_context* ctx, uint64_t sf, uint64_t op, uint64_t S, uint64_t sh, uint64_t imm12, uint64_t Rn, uint64_t Rd);
void add_subtract_shifted_jit(ssa_emit_context* ctx, uint64_t sf, uint64_t op, uint64_t S, uint64_t shift, uint64_t Rm, uint64_t imm6, uint64_t Rn, uint64_t Rd);
void add_subtract_extended_jit(ssa_emit_context* ctx, uint64_t sf, uint64_t op, uint64_t S, uint64_t Rm, uint64_t option, uint64_t imm3, uint64_t Rn, uint64_t Rd);
@@ -445,6 +467,7 @@ void multiply_with_32_jit(ssa_emit_context* ctx, uint64_t U, uint64_t Rm, uint64
void multiply_hi_jit(ssa_emit_context* ctx, uint64_t U, uint64_t Rm, uint64_t o0, uint64_t Rn, uint64_t Rd);
void multiply_additive_jit(ssa_emit_context* ctx, uint64_t sf, uint64_t Rm, uint64_t o0, uint64_t Ra, uint64_t Rn, uint64_t Rd);
void divide_jit(ssa_emit_context* ctx, uint64_t sf, uint64_t Rm, uint64_t o1, uint64_t Rn, uint64_t Rd);
uint64_t create_rbit_mask_jit(ssa_emit_context* ctx, uint64_t index);
void rbit_jit(ssa_emit_context* ctx, uint64_t sf, uint64_t Rn, uint64_t Rd);
void rev16_jit(ssa_emit_context* ctx, uint64_t sf, uint64_t Rn, uint64_t Rd);
void reverse_jit(ssa_emit_context* ctx, uint64_t sf, uint64_t opc, uint64_t Rn, uint64_t Rd);
@@ -480,6 +503,7 @@ void load_store_register_imm_unsigned_jit(ssa_emit_context* ctx, uint64_t size,
void load_store_register_imm_unscaled_jit(ssa_emit_context* ctx, uint64_t size, uint64_t VR, uint64_t opc, uint64_t imm9, uint64_t wb, uint64_t Rn, uint64_t Rt);
void load_store_register_offset_jit(ssa_emit_context* ctx, uint64_t size, uint64_t VR, uint64_t opc, uint64_t Rm, uint64_t option, uint64_t S, uint64_t Rn, uint64_t Rt);
void load_store_exclusive_ordered_jit(ssa_emit_context* ctx, uint64_t size, uint64_t ordered, uint64_t L, uint64_t Rs, uint64_t o0, uint64_t Rn, uint64_t Rt);
ir_operand exclusive_address_mask_jit(ssa_emit_context* ctx);
void load_exclusive_jit(ssa_emit_context* ctx, uint64_t is_exclusive, uint64_t size, uint64_t Rn, uint64_t Rt);
void store_exclusive_jit(ssa_emit_context* ctx, uint64_t is_exclusive, uint64_t size, uint64_t Rn, uint64_t Rt, uint64_t Rs);
void conversion_between_floating_point_and_fixed_point_jit(ssa_emit_context* ctx, uint64_t sf, uint64_t S, uint64_t ftype, uint64_t rmode, uint64_t opcode, uint64_t scale, uint64_t Rn, uint64_t Rd);
@@ -505,6 +529,12 @@ void fmul_vector_by_element_jit(ssa_emit_context* ctx, uint64_t Q, uint64_t sz,
void fmul_accumulate_scalar_jit(ssa_emit_context* ctx, uint64_t sz, uint64_t L, uint64_t M, uint64_t Rm, uint64_t neg, uint64_t H, uint64_t Rn, uint64_t Rd);
void fmul_accumulate_element_jit(ssa_emit_context* ctx, uint64_t Q, uint64_t sz, uint64_t L, uint64_t M, uint64_t Rm, uint64_t neg, uint64_t H, uint64_t Rn, uint64_t Rd);
void faddp_scalar_jit(ssa_emit_context* ctx, uint64_t sz, uint64_t Rn, uint64_t Rd);
void fcmeq_vector_zero_jit(ssa_emit_context* ctx, uint64_t Q, uint64_t sz, uint64_t Rn, uint64_t Rd);
void fcmgt_vector_zero_jit(ssa_emit_context* ctx, uint64_t Q, uint64_t sz, uint64_t Rn, uint64_t Rd);
void fcmge_vector_zero_jit(ssa_emit_context* ctx, uint64_t Q, uint64_t sz, uint64_t Rn, uint64_t Rd);
void fcmeq_vector_register_jit(ssa_emit_context* ctx, uint64_t Q, uint64_t sz, uint64_t Rm, uint64_t Rn, uint64_t Rd);
void fcmgt_vector_register_jit(ssa_emit_context* ctx, uint64_t Q, uint64_t sz, uint64_t Rm, uint64_t Rn, uint64_t Rd);
void fcmge_vector_register_jit(ssa_emit_context* ctx, uint64_t Q, uint64_t sz, uint64_t Rm, uint64_t Rn, uint64_t Rd);
void fadd_scalar_jit(ssa_emit_context* ctx, uint64_t ftype, uint64_t Rm, uint64_t Rn, uint64_t Rd);
void fsub_scalar_jit(ssa_emit_context* ctx, uint64_t ftype, uint64_t Rm, uint64_t Rn, uint64_t Rd);
void fmul_scalar_jit(ssa_emit_context* ctx, uint64_t ftype, uint64_t Rm, uint64_t Rn, uint64_t Rd);
@@ -573,12 +603,6 @@ void st2_multiple_structures_no_offset_jit(ssa_emit_context* ctx, uint64_t Q, ui
void st2_multiple_structures_post_index_jit(ssa_emit_context* ctx, uint64_t Q, uint64_t Rm, uint64_t size, uint64_t Rn, uint64_t Rt);
void st1_single_structure_no_offset_jit(ssa_emit_context* ctx, uint64_t Q, uint64_t opcode, uint64_t S, uint64_t size, uint64_t Rn, uint64_t Rt);
void st1_single_structure_post_index_jit(ssa_emit_context* ctx, uint64_t Q, uint64_t Rm, uint64_t opcode, uint64_t S, uint64_t size, uint64_t Rn, uint64_t Rt);
void fcmeq_vector_zero_jit(ssa_emit_context* ctx, uint64_t Q, uint64_t sz, uint64_t Rn, uint64_t Rd);
void fcmgt_vector_zero_jit(ssa_emit_context* ctx, uint64_t Q, uint64_t sz, uint64_t Rn, uint64_t Rd);
void fcmge_vector_zero_jit(ssa_emit_context* ctx, uint64_t Q, uint64_t sz, uint64_t Rn, uint64_t Rd);
void fcmeq_vector_register_jit(ssa_emit_context* ctx, uint64_t Q, uint64_t sz, uint64_t Rm, uint64_t Rn, uint64_t Rd);
void fcmgt_vector_register_jit(ssa_emit_context* ctx, uint64_t Q, uint64_t sz, uint64_t Rm, uint64_t Rn, uint64_t Rd);
void fcmge_vector_register_jit(ssa_emit_context* ctx, uint64_t Q, uint64_t sz, uint64_t Rm, uint64_t Rn, uint64_t Rd);
void floating_point_conditional_select_jit(ssa_emit_context* ctx, uint64_t ftype, uint64_t Rm, uint64_t cond, uint64_t Rn, uint64_t Rd);
void fcmp_jit(ssa_emit_context* ctx, uint64_t ftype, uint64_t Rm, uint64_t Rn, uint64_t opc);
void fccmp_jit(ssa_emit_context* ctx, uint64_t ftype, uint64_t Rm, uint64_t cond, uint64_t Rn, uint64_t nzcv);
@@ -598,6 +622,10 @@ uint64_t use_fast_float_jit(ssa_emit_context* ctx);//THIS FUNCTION IS USER DEFIN
uint64_t use_x86_sse_jit(ssa_emit_context* ctx);//THIS FUNCTION IS USER DEFINED
uint64_t use_x86_sse2_jit(ssa_emit_context* ctx);//THIS FUNCTION IS USER DEFINED
uint64_t use_x86_sse41_jit(ssa_emit_context* ctx);//THIS FUNCTION IS USER DEFINED
uint64_t use_x86_jit(ssa_emit_context* ctx);//THIS FUNCTION IS USER DEFINED
uint64_t use_x86_lzcnt_jit(ssa_emit_context* ctx);//THIS FUNCTION IS USER DEFINED
ir_operand x86_add_set_flags_jit(ssa_emit_context* ctx,uint64_t O, ir_operand n, ir_operand m);//THIS FUNCTION IS USER DEFINED
ir_operand x86_subtract_set_flags_jit(ssa_emit_context* ctx,uint64_t O, ir_operand n, ir_operand m);//THIS FUNCTION IS USER DEFINED
uint64_t _get_pc_jit(ssa_emit_context* ctx);//THIS FUNCTION IS USER DEFINED
ir_operand translate_address_jit(ssa_emit_context* ctx, ir_operand address);//THIS FUNCTION IS USER DEFINED
void call_supervisor_jit(ssa_emit_context* ctx, uint64_t svc);//THIS FUNCTION IS USER DEFINED
+1
View File
@@ -22,6 +22,7 @@ static T compare_and_swap_impl(uint64_t address_src, T expecting, T to_swap)
return false;
}
//TODO: account for unalgined pointer
static uint64_t compare_and_swap_interpreter_cpp(uint64_t physical_address, uint64_t expecting, uint64_t to_swap, uint64_t size)
{
global_lock.lock();
+14 -2
View File
@@ -23,6 +23,7 @@ void guest_process::create(guest_process* result, guest_memory guest_memory_cont
result->guest_functions.use_flt = true;
result->guest_functions.retranslator_is_running = false;
result->log_native = nullptr;
init_aarch64_decoder(result);
}
@@ -40,7 +41,7 @@ uint64_t guest_process::jit_function(guest_process* process, uint64_t guest_func
void* arguments[] = { arm_context };
if (function_to_execute.times_executed == 100 && !process->debug_mode)
if (function_to_execute.times_executed == 1000 && !process->debug_mode)
{
switch (function_to_execute.optimizations)
{
@@ -106,6 +107,10 @@ guest_function guest_process::translate_function(translate_request_data* data, g
ssa_emit_context::reset_local(&ssa_emit);
ssa_emit.memory_base = ssa_emit_context::create_global(&ssa_emit, int64);
ir_operation_block::emitds(raw_ir, ir_move, ssa_emit.memory_base, ir_operand::create_con((uint64_t)process->guest_memory_context.base));
while (true)
{
std::unordered_set<uint64_t> to_compile_que = aarch64_emit.basic_block_translate_que;
@@ -204,7 +209,14 @@ guest_function guest_process::translate_function(translate_request_data* data, g
backend_compiler_flags = compiler_flags::optimize_ssa | compiler_flags::mathmatical_fold;
}
void* code = jit_context::compile_code(process->host_jit_context, raw_ir,(compiler_flags)backend_compiler_flags);
uint64_t code_size;
void* code = jit_context::compile_code(process->host_jit_context, raw_ir,(compiler_flags)backend_compiler_flags, &code_size);
if (((guest_process*)data->process)->log_native != nullptr && flags == guest_compiler_optimization_flags::level_three)
{
((void(*)(void*, int))((guest_process*)data->process)->log_native)(code, code_size);
}
guest_function result;
+1
View File
@@ -25,6 +25,7 @@ struct guest_process
void* counter_function;
void* undefined_instruction;
bool debug_mode;
void* log_native;
cpu_type process_type;
cpu_size process_size;
+2
View File
@@ -9,6 +9,8 @@ struct ssa_emit_context
uint64_t local_top;
uint64_t global_bottom;
ir_operand memory_base;
void* context_data;
static void create(ssa_emit_context* ctx, ir_operation_block* ir);
+6 -2
View File
@@ -22,7 +22,7 @@ static void base_plus_va_jit(void* memory, ssa_emit_context* ir, ir_operand dest
{
ir_operation_block* ctx = ir->ir;
ir_operation_block::emitds(ctx, ir_add, destination, source, ir_operand::create_con((uint64_t)memory));
ir_operation_block::emitds(ctx, ir_add, destination, source, ir->memory_base);
}
extern "C"
@@ -31,6 +31,8 @@ extern "C"
{
external_context* result = new external_context;
result->process.log_native = nullptr;
jit_context::create(&result->memory, 5ULL * 1024 * 1024 * 1024, get_abi());
guest_process::create(&result->process, {memory, base_plus_va, base_plus_va_jit}, &result->memory, *context_offsets);
@@ -53,8 +55,10 @@ extern "C"
return guest_process::interperate_function(&context->process, virtual_address, guest_context, is_running);
}
EXPORT uint64_t jit_until_long_jump(external_context* context, uint64_t virtual_address, void* guest_context, bool* is_running)
EXPORT uint64_t jit_until_long_jump(external_context* context, uint64_t virtual_address, void* guest_context, bool* is_running, void* log_native)
{
context->process.log_native = log_native;
while (*is_running)
{
virtual_address = guest_process::jit_function(&context->process, virtual_address, guest_context);
+44 -2
View File
@@ -85,7 +85,6 @@ enum ir_instructions : uint64_t
//Abi
ir_close_and_return,
ir_compare_and_swap,
ir_get_argument,
ir_external_call,
ir_table_jump,
@@ -144,6 +143,18 @@ enum ir_instructions : uint64_t
x86_subsd,
x86_subss,
x86_paddb,
x86_paddw,
x86_paddd,
x86_paddq,
x86_cmpss,
x86_cmpsd,
x86_cmpps,
x86_cmppd,
x86_haddps,
x86_haddpd,
x86_xorps,
x86_pand,
x86_orps,
@@ -158,6 +169,16 @@ enum ir_instructions : uint64_t
x86_sqrtsd,
x86_sqrtps,
x86_sqrtpd,
x86_popcnt,
x86_cvtsd2ss,
x86_cvtss2sd,
x86_add_flags,
x86_sub_flags,
x86_cmpxchg,
x86_lzcnt,
//Emulator Helpers
ir_guest_store_context,
@@ -239,7 +260,6 @@ static std::string instruction_names[] = {
//Abi
"ir_close_and_return",
"ir_compare_and_swap",
"ir_get_argument",
"ir_external_call",
"ir_table_jump",
@@ -298,6 +318,18 @@ static std::string instruction_names[] = {
"x86_subsd",
"x86_subss",
"x86_paddb",
"x86_paddw",
"x86_paddd",
"x86_paddq",
"x86_cmpss",
"x86_cmpsd",
"x86_cmpps",
"x86_cmppd",
"x86_haddps",
"x86_haddpd",
"x86_xorps",
"x86_pand",
"x86_orps",
@@ -312,6 +344,16 @@ static std::string instruction_names[] = {
"x86_sqrtsd",
"x86_sqrtps",
"x86_sqrtpd",
"x86_popcnt",
"x86_cvtsd2ss",
"x86_cvtss2sd",
"x86_add_flags",
"x86_sub_flags",
"x86_cmpxchg",
"x86_lzcnt",
//Emulator Helpers
"ir_guest_store_context",
+3
View File
@@ -435,6 +435,9 @@ std::string ir_operation_block::get_block_log(ir_operation_block* ir)
{
ir_operation working_operation = i->data;
if (working_operation.instruction == ir_no_operation)
continue;
std::string name = instruction_names[working_operation.instruction];
result += name + " ";
+193 -19
View File
@@ -490,6 +490,13 @@ static uint64_t get_mask(int size)
throw_error();
}
static void empty_operation(ir_operation* operation)
{
operation->sources.count = 0;
operation->destinations.count = 0;
operation->instruction = ir_no_operation;
}
static bool perform_move_propagation(ssa_cf_node* node)
{
bool done = true;
@@ -537,9 +544,7 @@ static bool perform_move_propagation(ssa_cf_node* node)
break;
}
i->data.instruction = ir_no_operation;
i->data.destinations.count = 0;
i->data.sources.count = 0;
empty_operation(&i->data);
done = false;
}
@@ -547,6 +552,104 @@ static bool perform_move_propagation(ssa_cf_node* node)
return done;
}
static bool perform_load_store_addition_propagation(ssa_cf_node* node, std::unordered_map<uint64_t, std::unordered_map<ssa_cf_node*, uint64_t>>* usage_count_map)
{
bool done = true;
ssa_context* ctx = node->context;
for (auto i = node->raw_node->entry_instruction; i != node->raw_node->final_instruction->next; i = i->next)
{
auto working_instruction = i->data;
int ins = working_instruction.instruction;
if (ins != ir_load && ins != ir_store)
continue;
if ((working_instruction.sources.count == 2 && ins == ir_load) || (working_instruction.sources.count == 3 && ins == ir_store))
continue;
ir_operand source = i->data.sources[0];
if (ir_operand::is_constant(&source))
continue;
if (is_global(ctx, source))
continue;
if ((*usage_count_map)[source.value][node] > 2)
{
continue;
}
ir_operation* to_nop = nullptr;
for (auto s = i->prev; s != nullptr; s = s->prev)
{
ir_operation* check_instruction = &s->data;
if (check_instruction->destinations.count != 1)
continue;
ir_operand destination_check = check_instruction->destinations[0];
if (ir_operand::are_equal(destination_check, source))
{
to_nop = check_instruction;
break;
}
if (s == node->raw_node->entry_instruction)
break;
if (s->data.instruction == ir_mark_label)
{
throw_error();
}
}
if (to_nop == nullptr)
{
throw_error();
}
if (to_nop->instruction != ir_add)
continue;
if (ins == ir_load)
{
ir_operation_block::emit_with(ctx->ir, ir_load, working_instruction.destinations.data, 1, to_nop->sources.data, 2, i);
}
else if (ins == ir_store)
{
ir_operand new_sources[3];
new_sources[0] = to_nop->sources[0];
new_sources[1] = to_nop->sources[1];
new_sources[2] = working_instruction.sources[1];
ir_operation_block::emit_with(ctx->ir, ir_store, nullptr, 0, new_sources, 3, i);
}
empty_operation(&i->data);
empty_operation(to_nop);
done = false;
}
return done;
}
static void swap(ir_operand* l, ir_operand* r)
{
ir_operand tmp = *l;
*l = *r;
*r = tmp;
}
static bool perform_global_move_propagation(ssa_cf_node* node, std::unordered_map<uint64_t, std::unordered_map<ssa_cf_node*, uint64_t>>* usage_count_map)
{
bool done = true;
@@ -575,17 +678,15 @@ static bool perform_global_move_propagation(ssa_cf_node* node, std::unordered_ma
ir_operand* to_replace = nullptr;
int usage_count = 0;
if ((*usage_count_map)[source.value][node] > 1)
{
continue;
}
for (auto s = i->prev; s != nullptr; s = s->prev)
{
ir_operation* check_instruction = &s->data;
if (check_if_local_used(s->data.sources.data, s->data.sources.count, source.value))
{
break;
}
if (check_instruction->destinations.count != 1)
continue;
@@ -612,8 +713,23 @@ static bool perform_global_move_propagation(ssa_cf_node* node, std::unordered_ma
continue;
}
if (usage_count != 0)
break;
for (auto s = i->next; s != nullptr; s = s->next)
{
if (check_if_local_used(s->data.sources.data, s->data.sources.count, source.value))
{
to_replace = nullptr;
break;
}
if (s == node->raw_node->final_instruction)
break;
}
if (to_replace == nullptr)
{
continue;
}
to_replace->value = destination.value;
@@ -627,6 +743,40 @@ static bool perform_global_move_propagation(ssa_cf_node* node, std::unordered_ma
return done;
}
static bool perform_dead_code_elimination(ssa_cf_node* node, std::unordered_map<uint64_t, std::unordered_map<ssa_cf_node*, uint64_t>>* usage_count_map)
{
bool done = true;
ssa_context* ctx = node->context;
for (auto i = node->raw_node->entry_instruction; i != node->raw_node->final_instruction->next; i = i->next)
{
auto working_instruction = i->data;
if (working_instruction.instruction == ir_external_call)
continue;
if (working_instruction.destinations.count != 1)
continue;
ir_operand destination = working_instruction.destinations[0];
if (is_global(ctx,destination))
continue;
if ((*usage_count_map)[destination.value][node] >= 1)
continue;
i->data.instruction = ir_no_operation;
i->data.destinations.count = 0;
i->data.sources.count = 0;
done = false;
}
return done;
}
static bool perform_math_propagation(ssa_cf_node* node)
{
bool done = true;
@@ -655,6 +805,28 @@ static bool perform_math_propagation(ssa_cf_node* node)
}; break;
case ir_load:
{
if (working_instruction->sources.count == 2)
{
if (ir_operand::is_constant(&sources[0]) && !ir_operand::is_constant(&sources[1]))
{
swap(&sources[0], &sources[1]);
done = false;
}
else if (ir_operand::is_constant(&sources[0]) && ir_operand::is_constant(&sources[1]))
{
ir_operand new_operand = ir_operand::create_con(sources[0].value + sources[1].value, sources[0].meta_data);
sources[0] = new_operand;
working_instruction->sources.count = 1;
done = false;
}
}
}; break;
case ir_add:
{
if (check_constant(sources[0], 0))
@@ -914,13 +1086,6 @@ void ssa_construct_and_optimize(ir_operation_block* source, compiler_flags flags
remap_ssa_sources(&ctx, &ssa_node_store[i]);
}
std::unordered_map<uint64_t, std::unordered_map<ssa_cf_node*, uint64_t>> total_register_usage_count;
for (int i = 0; i < count; ++i)
{
append_usage_data_global(nullptr, &total_register_usage_count, &ssa_node_store[i]);
}
//ir_operation_block::log(source);
if (flags & compiler_flags::mathmatical_fold)
@@ -929,6 +1094,13 @@ void ssa_construct_and_optimize(ir_operation_block* source, compiler_flags flags
{
bool done = true;
std::unordered_map<uint64_t, std::unordered_map<ssa_cf_node*, uint64_t>> total_register_usage_count;
for (int i = 0; i < count; ++i)
{
append_usage_data_global(nullptr, &total_register_usage_count, &ssa_node_store[i]);
}
for (int i = 0; i < count; ++i)
{
ssa_cf_node* working_node = &ssa_node_store[i];
@@ -936,6 +1108,8 @@ void ssa_construct_and_optimize(ir_operation_block* source, compiler_flags flags
done &= perform_move_propagation(working_node);
done &= perform_math_propagation(working_node);
done &= perform_global_move_propagation(working_node, &total_register_usage_count);
done &= perform_load_store_addition_propagation(working_node, &total_register_usage_count);
done &= perform_dead_code_elimination(working_node, &total_register_usage_count);
}
if (done)
+6 -1
View File
@@ -67,7 +67,7 @@ void* jit_context::append_to_jit_cache(jit_context* context, void* source_functi
return growing_jit_cache::append_code(&context->jit_cache, source_function, function_size);
}
void* jit_context::compile_code(jit_context* context, ir_operation_block* ir_operation_block_context, compiler_flags flags)
void* jit_context::compile_code(jit_context* context, ir_operation_block* ir_operation_block_context, compiler_flags flags, uint64_t* code_size_result)
{
void* code_buffer;
uint64_t code_size;
@@ -84,5 +84,10 @@ void* jit_context::compile_code(jit_context* context, ir_operation_block* ir_ope
default: throw_error();
}
if (code_size_result != nullptr)
{
*code_size_result = code_size;
}
return jit_context::append_to_jit_cache(context, code_buffer, code_size);
}
+1 -1
View File
@@ -16,7 +16,7 @@ struct jit_context
static void create_from_host(jit_context* result, uint64_t allocation_size);
static uint64_t call_jitted_function(jit_context* context, void* function, uint64_t* arguments);
static void* append_to_jit_cache(jit_context* context, void* source_function, uint64_t function_size);
static void* compile_code(jit_context* context, ir_operation_block* ir_operation_block_context, compiler_flags flags);
static void* compile_code(jit_context* context, ir_operation_block* ir_operation_block_context, compiler_flags flags, uint64_t* code_size_result = nullptr);
};
#endif