added SSA

This commit is contained in:
Mphatso Raymond Mataka
2025-01-12 22:54:30 -08:00
parent 1a9d04773a
commit f994267695
21 changed files with 971 additions and 57 deletions
+4 -1
View File
@@ -3,7 +3,10 @@
enum compiler_flags
{
check_undefined_behavior = 1ULL << 0,
check_undefined_behavior = 1ULL << 0,
optimize_ssa = 1ULL << 1,
mathmatical_fold = optimize_ssa | 1ULL << 2,
pointer_loading_fold = optimize_ssa | 1ULL << 3,
};
#endif
+31 -2
View File
@@ -438,7 +438,10 @@ void assemble_x86_64_code(void** result_code, uint64_t* result_code_size, ir_ope
{
uint64_t imm = sources[1].value;
assert(imm <= INT32_MAX);
if (imm >= INT32_MAX)
{
throw_error();
}
switch (instruction)
{
@@ -486,6 +489,7 @@ void assemble_x86_64_code(void** result_code, uint64_t* result_code_size, ir_ope
}; break;
case ir_close_and_return:
case ir_table_jump:
{
ir_operand value = working_operation.sources[0];
ir_operand context_size = working_operation.sources[1];
@@ -502,7 +506,14 @@ void assemble_x86_64_code(void** result_code, uint64_t* result_code_size, ir_ope
c.mov(c.rax, create_operand<Xbyak::Reg64>(value));
}
c.ret();
if (instruction == ir_close_and_return)
{
c.ret();
}
else
{
c.jmp(c.rax);
}
}; break;
@@ -740,6 +751,24 @@ void assemble_x86_64_code(void** result_code, uint64_t* result_code_size, ir_ope
c.movq(create_operand<Xbyak::Xmm>(d), create_operand<Xbyak::Reg64>(s));
}; break;
case x86_lea:
{
assert_operand_count(&working_operation, 1, 2);
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();
}
}; 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;
+6
View File
@@ -2,6 +2,7 @@
#include "x86_pre_allocator.h"
#include "x86_assembler.h"
#include "debugging.h"
#include "ir/ssa.h"
#include "ir/basic_register_allocator.h"
#include "ir/undefined_behavior_check.h"
@@ -28,6 +29,11 @@ void assemble_x86_64_pipeline(void** result_code, uint64_t* result_code_size, ir
source_ir = undefined_behavior_checked_code;
}
if (flags & optimize_ssa)
{
ssa_construct_and_optimize(source_ir, flags);
}
x86_pre_allocator_context::run_pass(&pre_allocation_data, pre_allocated_code, source_ir, working_abi.cpu,working_abi.os);
+97 -22
View File
@@ -169,26 +169,78 @@ static void emit_conditional_select(x86_pre_allocator_context* result, ir_operan
}
}
static void emit_d_n_f_d_n_m(x86_pre_allocator_context* result, uint64_t instruction, ir_operand destination, ir_operand source_0, ir_operand source_1)
static bool instruction_is_commutative(uint64_t instruction)
{
switch (instruction)
{
case ir_add:
case ir_multiply:
case ir_bitwise_and:
case ir_bitwise_or:
case ir_bitwise_exclusive_or:
{
return true;
};
}
return false;
}
static void swap(ir_operand* l, ir_operand* r)
{
ir_operand tmp = *l;
*l = *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)
{
assert_same_size({ destination, source_0, source_1 });
if (instruction_is_commutative(instruction) && ir_operand::is_constant(&source_0) && !ir_operand::is_constant(&source_1))
{
swap(&source_0, &source_1);
}
if ((ir_operand::is_constant(&source_1) && source_1.value < INT32_MAX) && !ir_operand::is_constant(&source_0))
{
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);
ir_operand working_scrap = create_scrap_operand(result, destination.meta_data);
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);
}
else
{
ir_operand working_scrap = create_scrap_operand(result, destination.meta_data);
//ins destination source_0 source_1
//mov scrap source_0
emit_move(result, working_scrap, working_source_0);
//ins scrap source_1
ir_operation_block::emitds(result->ir, instruction, working_scrap, working_scrap, working_source_1);
//mov destination scrap
emit_move(result, working_destination, working_scrap);
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);
}
}
static void emit_floating_point_compare(x86_pre_allocator_context* result, uint64_t instruction, ir_operand destination, ir_operand source_0, ir_operand source_1)
@@ -271,6 +323,18 @@ static void emit_shift(x86_pre_allocator_context* result, uint64_t instruction,
{
assert_same_size({ destination, source_0, source_1 });
if ((ir_operand::is_constant(&source_1) && source_1.value < 255) && !ir_operand::is_constant(&source_0))
{
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);
@@ -332,9 +396,14 @@ static void emit_d_f_d_n(x86_pre_allocator_context* result, uint64_t instruction
assert_is_register(destination);
ir_operand working_destination = destination;
ir_operand working_source_0 = register_or_constant(result, &source);
emit_move(result, working_destination, working_source_0);
if (!ir_operand::are_equal(destination, source))
{
ir_operand working_source_0 = register_or_constant(result, &source);
emit_move(result, working_destination, working_source_0);
}
ir_operation_block::emitds(result->ir, instruction, working_destination, working_destination);
}
@@ -428,20 +497,20 @@ static void emit_big_multiply_divide(x86_pre_allocator_context* result, uint64_t
ir_operation_block::emits(result->ir, ir_instructions::ir_register_allocator_p_unlock, ax);
}
static void emit_return(x86_pre_allocator_context* result, ir_operand to_return)
static void emit_context_exit(x86_pre_allocator_context* result, uint64_t instruction, ir_operand new_location)
{
int raw_size = ir_operand::get_raw_size(&to_return);
int raw_size = ir_operand::get_raw_size(&new_location);
to_return = register_or_constant(result, &to_return, raw_size != int64);
new_location = register_or_constant(result, &new_location, raw_size != int64);
to_return.meta_data = int64;
new_location.meta_data = int64;
if (raw_size <= int16)
{
ir_operation_block::emitds(result->ir,ir_bitwise_and, to_return, to_return, ir_operand::create_con((1 << (8 << raw_size)) - 1));
ir_operation_block::emitds(result->ir,ir_bitwise_and, new_location, new_location, ir_operand::create_con((1 << (8 << raw_size)) - 1));
}
ir_operation_block::emits(result->ir, ir_instructions::ir_close_and_return,to_return , ir_operand::create_con(0));
ir_operation_block::emits(result->ir, instruction, new_location , ir_operand::create_con(0));
intrusive_linked_list< intrusive_linked_list_element<ir_operation>*>::insert_element(result->revisit_instructions, result->ir->operations->last->prev);
}
@@ -512,7 +581,11 @@ static void emit_vector_insert(x86_pre_allocator_context* result, ir_operation*
assert_is_constant(index);
assert_is_constant(size);
emit_move(result, destination, source_vector);
if (!ir_operand::are_equal(destination, source_vector))
{
emit_move(result, destination, source_vector);
}
ir_operation_block::emitds(result->ir, ir_vector_insert, destination, destination, value, index, size);
}
@@ -777,10 +850,11 @@ static void emit_pre_allocation_instruction(x86_pre_allocator_context* pre_alloc
//ABI
case ir_close_and_return:
case ir_table_jump:
{
assert_operand_count(operation, 0, 1);
emit_return(pre_allocator_context, operation->sources[0]);
emit_context_exit(pre_allocator_context, working_instruction, operation->sources[0]);
}; break;
@@ -985,6 +1059,7 @@ void x86_pre_allocator_context::run_pass(x86_pre_allocator_context* pre_allocato
} break;
case ir_close_and_return:
case ir_table_jump:
{
working_element->data.sources[1].value = context_size;
} break;
+41 -2
View File
@@ -1,6 +1,7 @@
#include "aarch64_emit_context.h"
#include "emulator/ssa_emit_context.h"
#include "emulator/guest_process.h"
#include "jit/jit_memory.h"
void aarch64_emit_context::create(guest_process* process, aarch64_emit_context* result, ssa_emit_context* ssa)
{
@@ -60,8 +61,41 @@ void aarch64_emit_context::emit_store_context(aarch64_emit_context* ctx)
ctx->context_movement.push_back(ir_operation_block::emits(ir, ir_guest_store_context, ctx->context_pointer));
}
void aarch64_emit_context::branch_long(aarch64_emit_context* ctx, ir_operand new_location, bool store_context)
{
static void table_branch(aarch64_emit_context* ctx, ir_operand address)
{
guest_process* process = ctx->process;
ir_operation_block* ir = ctx->raw_ir;
auto table = &process->guest_functions.native_function_table;
if (!fast_function_table::is_open(table))
{
return;
}
ir_operand end = ir_operation_block::create_label(ir);
ir_operand table_base = ir_operand::create_con((uint64_t)table->function_store);
address = ssa_emit_context::emit_ssa(ctx->ssa, ir_subtract, address, ir_operand::create_con(table->entry_address));
ir_operation_block::jump_if(ir, end, ssa_emit_context::emit_ssa(ctx->ssa, ir_compare_greater_equal_unsigned, address, ir_operand::create_con(table->function_store_size)));
ir_operand value_test = ssa_emit_context::emit_ssa(ctx->ssa, ir_load, ssa_emit_context::emit_ssa(ctx->ssa, ir_add, address, table_base), int32);
ir_operation_block::jump_if(ir, end, ssa_emit_context::emit_ssa(ctx->ssa, ir_compare_equal, value_test, ir_operand::create_con(UINT32_MAX, int32)));
ir_operand jit_base = ir_operand::create_con((uint64_t)process->host_jit_context->jit_cache.memory->raw_memory_block);
value_test = ir_operand::copy_new_raw_size(value_test, int64);
ir_operation_block::emits(ir, ir_table_jump, ssa_emit_context::emit_ssa(ctx->ssa, ir_add, jit_base, value_test));
ir_operation_block::mark_label(ir, end);
}
void aarch64_emit_context::branch_long(aarch64_emit_context* ctx, ir_operand new_location, bool store_context, bool allow_table_branch)
{
ctx->branch_state = branch_type::long_branch;
if (store_context)
@@ -69,6 +103,11 @@ void aarch64_emit_context::branch_long(aarch64_emit_context* ctx, ir_operand new
emit_store_context(ctx);
}
if (allow_table_branch)
{
table_branch(ctx, new_location);
}
ir_operation_block::emits(ctx->raw_ir, ir_close_and_return, new_location);
}
+1 -1
View File
@@ -33,7 +33,7 @@ struct aarch64_emit_context
static void init_context(aarch64_emit_context* ctx);
static void emit_load_context(aarch64_emit_context* ctx);
static void emit_store_context(aarch64_emit_context* ctx);
static void branch_long(aarch64_emit_context* ctx, ir_operand new_location, bool store_context = true);
static void branch_long(aarch64_emit_context* ctx, ir_operand new_location, bool store_context = true, bool allow_table_branch = true);
static void branch_short(aarch64_emit_context* ctx, ir_operand new_location);
static void emit_context_movement(aarch64_emit_context* ctx);
static ir_operand get_or_create_basic_block_label(aarch64_emit_context* ctx, uint64_t value);
@@ -170,6 +170,7 @@ void call_supervisor_jit(ssa_emit_context* ctx, uint64_t svc)
);
ir_operation_block::emits(ctx->ir,ir_close_and_return ,ir_operand::create_con(actx->current_instruction_address + 4));
actx->branch_state = branch_type::long_branch;
}
+42 -6
View File
@@ -4054,10 +4054,14 @@ uint64_t FPAdd_interpreter(interpreter_data* ctx, uint64_t operand1, uint64_t op
{
if (N == 32ULL)
{
uint32_t o1 = operand1;
uint32_t o2 = operand2;
return (undefined_value());
}
if (N == 64ULL)
{
uint64_t o1 = operand1;
uint64_t o2 = operand2;
return (undefined_value());
}
@@ -4071,10 +4075,14 @@ uint64_t FPSub_interpreter(interpreter_data* ctx, uint64_t operand1, uint64_t op
{
if (N == 32ULL)
{
uint32_t o1 = operand1;
uint32_t o2 = operand2;
return (undefined_value());
}
if (N == 64ULL)
{
uint64_t o1 = operand1;
uint64_t o2 = operand2;
return (undefined_value());
}
@@ -4088,10 +4096,14 @@ uint64_t FPMul_interpreter(interpreter_data* ctx, uint64_t operand1, uint64_t op
{
if (N == 32ULL)
{
uint32_t o1 = operand1;
uint32_t o2 = operand2;
return (undefined_value());
}
if (N == 64ULL)
{
uint64_t o1 = operand1;
uint64_t o2 = operand2;
return (undefined_value());
}
@@ -4105,10 +4117,14 @@ uint64_t FPDiv_interpreter(interpreter_data* ctx, uint64_t operand1, uint64_t op
{
if (N == 32ULL)
{
uint32_t o1 = operand1;
uint32_t o2 = operand2;
return (undefined_value());
}
if (N == 64ULL)
{
uint64_t o1 = operand1;
uint64_t o2 = operand2;
return (undefined_value());
}
@@ -4122,10 +4138,14 @@ uint64_t FPMax_interpreter(interpreter_data* ctx, uint64_t operand1, uint64_t op
{
if (N == 32ULL)
{
uint32_t o1 = operand1;
uint32_t o2 = operand2;
return (undefined_value());
}
if (N == 64ULL)
{
uint64_t o1 = operand1;
uint64_t o2 = operand2;
return (undefined_value());
}
@@ -4139,10 +4159,14 @@ uint64_t FPMin_interpreter(interpreter_data* ctx, uint64_t operand1, uint64_t op
{
if (N == 32ULL)
{
uint32_t o1 = operand1;
uint32_t o2 = operand2;
return (undefined_value());
}
if (N == 64ULL)
{
uint64_t o1 = operand1;
uint64_t o2 = operand2;
return (undefined_value());
}
@@ -9683,7 +9707,9 @@ ir_operand FPAdd_jit(ssa_emit_context* ctx, ir_operand operand1, ir_operand oper
{
uint64_t F = N == 32ULL ? int32 : N == 64ULL ? int64 : 0;
{
return copy_new_raw_size(ctx, ssa_emit_context::emit_ssa(ctx, ir_floating_point_add, copy_new_raw_size(ctx, operand1, F), copy_new_raw_size(ctx, operand2, F)), int64);
ir_operand o1 = copy_new_raw_size(ctx, operand1, F);
ir_operand o2 = copy_new_raw_size(ctx, operand2, F);
return copy_new_raw_size(ctx, ssa_emit_context::emit_ssa(ctx, ir_floating_point_add, o1, o2), int64);
}
}
return call_float_binary_jit(ctx,operand1,operand2,FPCR,N,(uint64_t)FPAdd_I);
@@ -9695,7 +9721,9 @@ ir_operand FPSub_jit(ssa_emit_context* ctx, ir_operand operand1, ir_operand oper
{
uint64_t F = N == 32ULL ? int32 : N == 64ULL ? int64 : 0;
{
return copy_new_raw_size(ctx, ssa_emit_context::emit_ssa(ctx, ir_floating_point_subtract, copy_new_raw_size(ctx, operand1, F), copy_new_raw_size(ctx, operand2, F)), int64);
ir_operand o1 = copy_new_raw_size(ctx, operand1, F);
ir_operand o2 = copy_new_raw_size(ctx, operand2, F);
return copy_new_raw_size(ctx, ssa_emit_context::emit_ssa(ctx, ir_floating_point_subtract, o1, o2), int64);
}
}
return call_float_binary_jit(ctx,operand1,operand2,FPCR,N,(uint64_t)FPSub_I);
@@ -9707,7 +9735,9 @@ ir_operand FPMul_jit(ssa_emit_context* ctx, ir_operand operand1, ir_operand oper
{
uint64_t F = N == 32ULL ? int32 : N == 64ULL ? int64 : 0;
{
return copy_new_raw_size(ctx, ssa_emit_context::emit_ssa(ctx, ir_floating_point_multiply, copy_new_raw_size(ctx, operand1, F), copy_new_raw_size(ctx, operand2, F)), int64);
ir_operand o1 = copy_new_raw_size(ctx, operand1, F);
ir_operand o2 = copy_new_raw_size(ctx, operand2, F);
return copy_new_raw_size(ctx, ssa_emit_context::emit_ssa(ctx, ir_floating_point_multiply, o1, o2), int64);
}
}
return call_float_binary_jit(ctx,operand1,operand2,FPCR,N,(uint64_t)FPMul_I);
@@ -9719,7 +9749,9 @@ ir_operand FPDiv_jit(ssa_emit_context* ctx, ir_operand operand1, ir_operand oper
{
uint64_t F = N == 32ULL ? int32 : N == 64ULL ? int64 : 0;
{
return copy_new_raw_size(ctx, ssa_emit_context::emit_ssa(ctx, ir_floating_point_divide, copy_new_raw_size(ctx, operand1, F), copy_new_raw_size(ctx, operand2, F)), int64);
ir_operand o1 = copy_new_raw_size(ctx, operand1, F);
ir_operand o2 = copy_new_raw_size(ctx, operand2, F);
return copy_new_raw_size(ctx, ssa_emit_context::emit_ssa(ctx, ir_floating_point_divide, o1, o2), int64);
}
}
return call_float_binary_jit(ctx,operand1,operand2,FPCR,N,(uint64_t)FPDiv_I);
@@ -9731,7 +9763,9 @@ ir_operand FPMax_jit(ssa_emit_context* ctx, ir_operand operand1, ir_operand oper
{
uint64_t F = N == 32ULL ? int32 : N == 64ULL ? int64 : 0;
{
return copy_new_raw_size(ctx, ssa_emit_context::emit_ssa(ctx, ir_floating_point_select_max, copy_new_raw_size(ctx, operand1, F), copy_new_raw_size(ctx, operand2, F)), int64);
ir_operand o1 = copy_new_raw_size(ctx, operand1, F);
ir_operand o2 = copy_new_raw_size(ctx, operand2, F);
return copy_new_raw_size(ctx, ssa_emit_context::emit_ssa(ctx, ir_floating_point_select_max, o1, o2), int64);
}
}
return call_float_binary_jit(ctx,operand1,operand2,FPCR,N,(uint64_t)FPMax_I);
@@ -9743,7 +9777,9 @@ ir_operand FPMin_jit(ssa_emit_context* ctx, ir_operand operand1, ir_operand oper
{
uint64_t F = N == 32ULL ? int32 : N == 64ULL ? int64 : 0;
{
return copy_new_raw_size(ctx, ssa_emit_context::emit_ssa(ctx, ir_floating_point_select_min, copy_new_raw_size(ctx, operand1, F), copy_new_raw_size(ctx, operand2, F)), int64);
ir_operand o1 = copy_new_raw_size(ctx, operand1, F);
ir_operand o2 = copy_new_raw_size(ctx, operand2, F);
return copy_new_raw_size(ctx, ssa_emit_context::emit_ssa(ctx, ir_floating_point_select_min, o1, o2), int64);
}
}
return call_float_binary_jit(ctx,operand1,operand2,FPCR,N,(uint64_t)FPMin_I);
+75
View File
@@ -0,0 +1,75 @@
#include "fast_function_table.h"
#include <string.h>
#include <iostream>
bool fast_function_table::is_open(fast_function_table* table)
{
return table->function_store != nullptr;
}
bool fast_function_table::insert_function(fast_function_table* table, uint64_t guest_address, uint32_t jit_offset)
{
if (!is_open(table))
{
init(table, guest_address);
}
guest_address -= table->entry_address;
if (guest_address >= table->function_store_size)
{
return false;
}
*(uint32_t*)((uint64_t)table->function_store + guest_address) = jit_offset;
return true;
}
fast_function_table::fast_function_table()
{
function_store = nullptr;
entry_address = -1;
function_store_size = -1;
}
void fast_function_table::init(fast_function_table* result, uint64_t entry_address)
{
result->entry_address = entry_address;
result->function_store_size = 100 * 1024 * 1024;
result->function_store = malloc(result->function_store_size);
memset(result->function_store, -1, result->function_store_size);
}
void fast_function_table::destroy(fast_function_table* to_destroy)
{
if (is_open(to_destroy))
{
free(to_destroy->function_store);
}
}
uint32_t fast_function_table::request_address(fast_function_table* table, uint64_t guest_address, bool* is_valid)
{
*is_valid = false;
if (!is_open(table))
{
return 0;
}
guest_address -= table->entry_address;
if (guest_address >= table->function_store_size)
{
return false;
}
uint32_t working_result = *(uint32_t*)((uint64_t)table->function_store + guest_address);
*is_valid = working_result != -1;
return working_result;
}
+22
View File
@@ -0,0 +1,22 @@
#ifndef FAST_FUNCTION_TABLE_H
#define FAST_FUNCTION_TABLE_H
#include <inttypes.h>
struct fast_function_table
{
uint64_t entry_address;
uint64_t function_store_size;
void* function_store;
fast_function_table();
static bool is_open(fast_function_table* test);
static bool insert_function(fast_function_table* table, uint64_t guest_address, uint32_t jit_offset);
static void init(fast_function_table* result, uint64_t entry_address);
static void destroy(fast_function_table* to_destroy);
static uint32_t request_address(fast_function_table* test, uint64_t guest_address, bool* is_valid);
};
#endif
+1
View File
@@ -6,6 +6,7 @@
struct guest_function
{
uint64_t times_executed;
uint32_t jit_offset;
void (*raw_function)(void* arguments);
};
+35
View File
@@ -1,8 +1,33 @@
#include "guest_function_store.h"
#include "ir/ir.h"
#include "guest_process.h"
#include "jit/jit_memory.h"
guest_function guest_function_store::get_or_translate_function(guest_function_store* context, uint64_t address, translate_request_data* process_context)
{
auto function_table = &context->native_function_table;
if (fast_function_table::is_open(function_table))
{
bool exists;
uint32_t jit_offset = fast_function_table::request_address(function_table, address, &exists);
if (exists)
{
guest_function result;
result.times_executed = 0;
result.jit_offset = jit_offset;
uint64_t jit_base = (uint64_t)((guest_process*)process_context->process)->host_jit_context->jit_cache.memory->raw_memory_block;
result.raw_function = (void(*)(void*))(jit_base + jit_offset);
return result;
}
}
context->lock.lock();
if (context->functions.find(address) == context->functions.end())
@@ -13,6 +38,11 @@ guest_function guest_function_store::get_or_translate_function(guest_function_st
context->lock.lock();
if (context->use_flt)
{
fast_function_table::insert_function(function_table, address, result.jit_offset);
}
context->functions[address] = result;
context->lock.unlock();
@@ -27,4 +57,9 @@ guest_function guest_function_store::get_or_translate_function(guest_function_st
return result;
}
}
void guest_function_store::destroy(guest_function_store* to_destory)
{
fast_function_table::destroy(&to_destory->native_function_table);
}
+5
View File
@@ -4,7 +4,9 @@
#include <unordered_map>
#include <inttypes.h>
#include <mutex>
#include "translate_request_data.h"
#include "fast_function_table.h"
struct guest_function_store;
struct translate_request_data;
@@ -14,8 +16,11 @@ struct guest_function_store
std::mutex lock;
std::unordered_map<uint64_t, guest_function> functions;
translate_guest_function translate_function_pointer;
fast_function_table native_function_table;
bool use_flt;
static guest_function get_or_translate_function(guest_function_store* context, uint64_t address, translate_request_data* process_context);
static void destroy(guest_function_store* to_destory);
};
#endif
+7 -4
View File
@@ -6,6 +6,7 @@
#include "aarch64/aarch64_process.h"
#include "aarch64/aarch64_impl.h"
#include "jit/jit_memory.h"
#include <iostream>
#include <iomanip>
@@ -19,6 +20,7 @@ void guest_process::create(guest_process* result, guest_memory guest_memory_cont
result->svc_function = nullptr;
result->undefined_instruction = nullptr;
result->debug_mode = false;
result->guest_functions.use_flt = true;
init_aarch64_decoder(result);
}
@@ -118,7 +120,7 @@ guest_function guest_process::translate_function(translate_request_data* data)
auto instruction_table = fixed_length_decoder<uint32_t>::decode_slow(&process->decoder, raw_instruction);
ssa_emit_context::reset_local(&ssa_emit);
//ssa_emit_context::reset_local(&ssa_emit);
if (instruction_table == nullptr)
{
@@ -157,14 +159,13 @@ guest_function guest_process::translate_function(translate_request_data* data)
aarch64_emit_context::emit_context_movement(&aarch64_emit);
//ir_operation_block::log(raw_ir);
void* code = jit_context::compile_code(process->host_jit_context, raw_ir,(compiler_flags)0);
void* code = jit_context::compile_code(process->host_jit_context, raw_ir,compiler_flags::optimize_ssa);
guest_function result;
result.times_executed = 0;
result.raw_function = (void(*)(void*))code;
result.jit_offset = (uint64_t)result.raw_function - (uint64_t)process->host_jit_context->jit_cache.memory->raw_memory_block;
arena_allocator::destroy(&allocator);
@@ -240,6 +241,8 @@ void guest_process::create(guest_process* result, guest_memory memory, jit_conte
void guest_process::destroy(guest_process* process)
{
guest_function_store::destroy(&process->guest_functions);
switch (process->process_type)
{
case arm:
+1 -1
View File
@@ -337,7 +337,7 @@ void basic_register_allocator_context::run_pass(basic_register_allocator_context
allocate_registers(result_register_allocator, new_sources, stack_max, working_operation.sources.data, working_operation.sources.count, register_mode::read);
allocate_registers(result_register_allocator, new_destinations, stack_max, working_operation.destinations.data, working_operation.destinations.count, register_mode::write);
if (ir_operation_block::is_label(instruction) || instruction == ir_external_call)
if (ir_operation_block::is_flow_critical(instruction) || instruction == ir_external_call)
{
unlock_all_basic(result_register_allocator);
+5 -1
View File
@@ -3,6 +3,7 @@
#include "ir.h"
#include <vector>
#include "debugging.h"
static void assert_operand_count(ir_operation* operation, int destinations, int sources)
{
@@ -90,7 +91,10 @@ static void assert_same_size(std::initializer_list<ir_operand> operands)
{
uint64_t working_size = operands.begin()[i].meta_data & UINT32_MAX;
assert(working_size == first_size);
if (working_size != first_size)
{
throw_error();
}
}
}
+28 -5
View File
@@ -84,6 +84,7 @@ enum ir_instructions : uint64_t
ir_compare_and_swap,
ir_get_argument,
ir_external_call,
ir_table_jump,
//Memory
ir_load,
@@ -94,6 +95,7 @@ enum ir_instructions : uint64_t
ir_open_context,
ir_register_allocator_p_lock,
ir_register_allocator_p_unlock,
ir_ssa_phi,
//Vectors
ir_vector_extract,
@@ -173,6 +175,17 @@ static std::string instruction_names[] = {
"ir_shift_right_signed",
"ir_shift_right_unsigned",
"ir_subtract",
"ir_floating_point_add",
"ir_floating_point_subtract",
"ir_floating_point_multiply",
"ir_floating_point_divide",
"ir_floating_point_select_min",
"ir_floating_point_select_max",
"ir_floating_point_compare_equal",
"ir_floating_point_compare_not_equal",
"ir_floating_point_compare_less",
"ir_floating_point_compare_greater",
"ir_floating_point_compare_greater_equal",
"ir_binary_end",
@@ -187,6 +200,7 @@ static std::string instruction_names[] = {
"ir_logical_not",
"ir_convert_to_float_signed",
"ir_convert_to_float_unsigned",
"ir_floating_point_square_root",
"ir_unary_end",
@@ -207,6 +221,7 @@ static std::string instruction_names[] = {
"ir_compare_and_swap",
"ir_get_argument",
"ir_external_call",
"ir_table_jump",
//Memory
"ir_load",
@@ -217,6 +232,7 @@ static std::string instruction_names[] = {
"ir_open_context",
"ir_register_allocator_p_lock",
"ir_register_allocator_p_unlock",
"ir_ssa_phi",
//Vectors
"ir_vector_extract",
@@ -227,7 +243,7 @@ static std::string instruction_names[] = {
"ir_assert_false",
"ir_assert_true",
//"x86
//x86
"x86_cqo",
"x86_cdq",
"x86_cwd",
@@ -258,6 +274,11 @@ static std::string instruction_names[] = {
"x86_subsd",
"x86_subss",
"x86_sqrtss",
"x86_sqrtsd",
"x86_sqrtps",
"x86_sqrtpd",
//Emulator Helpers
"ir_guest_store_context",
"ir_guest_load_context",
@@ -305,7 +326,7 @@ struct ir_operand
struct ir_operation
{
uint64_t instruction;
ir_instructions instruction;
fast_array<ir_operand> destinations;
fast_array<ir_operand> sources;
};
@@ -321,9 +342,11 @@ struct ir_operation_block
static void create_raw_operation(arena_allocator* allocator, ir_operation* result, uint64_t instruction, int destination_count, int source_count);
static void create_vector_gp_remap_scheme(arena_allocator* allocator, std::unordered_map<uint64_t, uint64_t>* remap_store, std::unordered_map<uint64_t, uint64_t>** remap_redirect);
static void clamp_operands(ir_operation_block* ir, bool use_bit_register_allocations, int* size_counts = nullptr);
static bool is_label(uint64_t instruction);
static bool is_label(ir_operation* operation);
static void ssa_remap(ir_operation_block* ir, std::unordered_map<uint64_t, uint64_t>* remap_data);
static bool is_flow_critical(uint64_t instruction);
static bool is_flow_critical(ir_operation* operation);
static ir_operand create_label(ir_operation_block* block);
static void mark_label(ir_operation_block* block, ir_operand label);
static void jump(ir_operation_block* block, ir_operand label);
+27 -3
View File
@@ -4,14 +4,38 @@ static ir_control_flow_node* create_and_insert_node(intrusive_linked_list<ir_con
{
ir_control_flow_node* result = arena_allocator::allocate_struct<ir_control_flow_node>(list->allocator);
intrusive_linked_list<ir_control_flow_node*>::insert_element(list, result);
result->entry_instruction = first_instruction;
result->final_instruction = block_final_instruction;
intrusive_linked_list<ir_control_flow_node*>::insert_element(list, result);
return result;
}
static bool is_label(ir_operation* operation)
{
switch (operation->instruction)
{
case ir_mark_label:
return true;
}
return false;
}
static bool is_jump(ir_operation* operation)
{
switch (operation->instruction)
{
case ir_jump_if:
case ir_close_and_return:
case ir_table_jump:
return true;
}
return false;
}
static void get_linier_nodes(ir_control_flow_graph* result)
{
ir_operation_block* source_ir = result->source_ir;
@@ -22,7 +46,7 @@ static void get_linier_nodes(ir_control_flow_graph* result)
{
ir_operation working_operation = i->data;
if (ir_operation_block::is_label(&working_operation))
if (is_jump(&working_operation) || (i->next != nullptr && is_label(&i->next->data)))
{
working_node->final_instruction = i;
+27 -9
View File
@@ -30,7 +30,7 @@ void ir_operation_block::create_raw_operation(arena_allocator* allocator, ir_ope
fast_array<ir_operand>::create(allocator, destination_count, &result->destinations);
fast_array<ir_operand>::create(allocator, source_count, &result->sources);
result->instruction = instruction;
result->instruction = (ir_instructions)instruction;
}
intrusive_linked_list_element<ir_operation>* ir_operation_block::emit(ir_operation_block* block, ir_operation operation, intrusive_linked_list_element<ir_operation>* point)
@@ -140,6 +140,21 @@ void ir_operation_block::clamp_operands(ir_operation_block* ir, bool use_bit_reg
}
}
void ir_operation_block::ssa_remap(ir_operation_block* ir, std::unordered_map<uint64_t, uint64_t>* remap_data)
{
std::unordered_map<uint64_t, uint64_t>* remap_redirection[ir_operand_meta::top];
for (int i = 0; i < ir_operand_meta::top; ++i)
{
remap_redirection[i] = remap_data;
}
for (auto i = ir->operations->first; i != ir->operations->last; i = i->next)
{
remap_operands_operations_impl(remap_redirection, &i->data, false);
}
}
intrusive_linked_list_element<ir_operation>* ir_operation_block::emit_with(ir_operation_block* ir, uint64_t instruction, ir_operand* destinations, int destination_count, ir_operand* sources, int source_count, intrusive_linked_list_element<ir_operation>* point)
{
ir_operation result;
@@ -302,7 +317,7 @@ intrusive_linked_list_element<ir_operation>* ir_operation_block::emits(ir_operat
return emit(ir, result, point);
}
bool ir_operation_block::is_label(uint64_t instruction)
bool ir_operation_block::is_flow_critical(uint64_t instruction)
{
switch (instruction)
{
@@ -315,9 +330,9 @@ bool ir_operation_block::is_label(uint64_t instruction)
}
}
bool ir_operation_block::is_label(ir_operation* operation)
bool ir_operation_block::is_flow_critical(ir_operation* operation)
{
return ir_operation_block::is_label(operation->instruction);
return ir_operation_block::is_flow_critical(operation->instruction);
}
ir_operand ir_operation_block::create_label(ir_operation_block* block)
@@ -333,6 +348,8 @@ ir_operand ir_operation_block::create_label(ir_operation_block* block)
void ir_operation_block::mark_label(ir_operation_block* block, ir_operand label)
{
ir_operation_block::emits(block, ir_mark_label, label);
ir_operation_block::emits(block, ir_no_operation);
}
void ir_operation_block::jump_if(ir_operation_block* block, ir_operand label, ir_operand condition)
@@ -394,11 +411,12 @@ std::string get_string(ir_operand value)
switch (raw_size)
{
case ir_operand_meta::int8: result += "INT8"; break;
case ir_operand_meta::int16: result += "INT16"; break;
case ir_operand_meta::int32: result += "INT32"; break;
case ir_operand_meta::int64: result += "INT64"; break;
case ir_operand_meta::int128: result += "INT128"; break;
case ir_operand_meta::int8: result += "INT8"; break;
case ir_operand_meta::int16: result += "INT16"; break;
case ir_operand_meta::int32: result += "INT32"; break;
case ir_operand_meta::int64: result += "INT64"; break;
case ir_operand_meta::int128: result += "INT128"; break;
case (ir_operand_meta)UINT32_MAX: result += "GENERIC"; break;
default: throw_error();
}
+506
View File
File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More