mirror of
https://github.com/pound-emu/rem.git
synced 2026-06-17 04:16:28 -07:00
Introduced even more aggressive optimizations.
This commit is contained in:
@@ -0,0 +1,24 @@
|
||||
#include "aarch64_assembler.h"
|
||||
#include <string.h>
|
||||
|
||||
#define ONE_MB 1 * 1024 * 1024
|
||||
|
||||
#define X(reg) rarma_context::X(reg)
|
||||
#define SP rarma_context::SP()
|
||||
#define WSP rarma_context::SP()
|
||||
|
||||
void assemble_aarch64_abi_caller_code(void* result_code, uint64_t* result_code_size, abi abi_information)
|
||||
{
|
||||
rarma_context c;
|
||||
|
||||
rarma_context::create(&c, ONE_MB);
|
||||
|
||||
rarma_context::sub_imm12(&c, SP, SP, 8);
|
||||
|
||||
rarma_context::add_imm12(&c, SP, SP, 8);
|
||||
|
||||
*result_code_size = c.memory_location;
|
||||
memcpy(result_code, c.memory_block, *result_code_size);
|
||||
|
||||
rarma_context::destroy(&c);
|
||||
}
|
||||
@@ -1,4 +1,11 @@
|
||||
#include <inttypes.h>
|
||||
#include "abi_information.h"
|
||||
|
||||
#ifndef AARCH64_ASSEMBLER_H
|
||||
#define AARCH64_ASSEMBLER_H
|
||||
|
||||
#include "rarma.h"
|
||||
|
||||
void assemble_aarch64_abi_caller_code(void* result_code, uint64_t* result_code_size, abi abi_information);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,322 @@
|
||||
#ifndef RARMA_H
|
||||
#define RARMA_H
|
||||
|
||||
#include <string>
|
||||
#include <inttypes.h>
|
||||
#include <iostream>
|
||||
#include <assert.h>
|
||||
|
||||
struct rarma_context
|
||||
{
|
||||
void* memory_block;
|
||||
|
||||
uint64_t memory_block_size;
|
||||
uint64_t memory_location;
|
||||
|
||||
enum operand_type
|
||||
{
|
||||
zr,
|
||||
sp,
|
||||
gp,
|
||||
vec
|
||||
};
|
||||
|
||||
enum shift_type
|
||||
{
|
||||
lsl,
|
||||
lsr,
|
||||
ror,
|
||||
asr
|
||||
};
|
||||
|
||||
struct operand
|
||||
{
|
||||
int operand_size;
|
||||
int operand_register_index;
|
||||
|
||||
operand_type type;
|
||||
};
|
||||
|
||||
static uint64_t get_code_size(rarma_context* context)
|
||||
{
|
||||
return context->memory_location;
|
||||
}
|
||||
|
||||
static operand gp_size(int index, int size, operand_type type)
|
||||
{
|
||||
operand result;
|
||||
|
||||
result.operand_size = size;
|
||||
result.operand_register_index = index;
|
||||
result.type = type;
|
||||
|
||||
assert_in_mask(index, 5);
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case sp:
|
||||
case zr:
|
||||
{
|
||||
assert(index == 31);
|
||||
|
||||
assert(size >= 2 && size <= 3);
|
||||
}; break;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static operand X(int index)
|
||||
{
|
||||
return gp_size(index, 3, operand_type::gp);
|
||||
}
|
||||
|
||||
static operand SP()
|
||||
{
|
||||
return gp_size(31, 3, operand_type::sp);
|
||||
}
|
||||
|
||||
static operand W(int index)
|
||||
{
|
||||
return gp_size(index, 2, operand_type::gp);
|
||||
}
|
||||
|
||||
static operand WSP()
|
||||
{
|
||||
return gp_size(31, 2, operand_type::sp);
|
||||
}
|
||||
|
||||
static operand H(int index)
|
||||
{
|
||||
return gp_size(index, 1, operand_type::gp);
|
||||
}
|
||||
|
||||
static operand B(int index)
|
||||
{
|
||||
return gp_size(index, 0, operand_type::gp);
|
||||
}
|
||||
|
||||
static void assert_is_gp_sp(operand test)
|
||||
{
|
||||
if (test.operand_register_index == 31)
|
||||
{
|
||||
assert(test.type == sp);
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(test.type == gp);
|
||||
}
|
||||
}
|
||||
|
||||
static void assert_is_gp_zr(operand test)
|
||||
{
|
||||
if (test.operand_register_index == 31)
|
||||
{
|
||||
assert(test.type == zr);
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(test.type == gp);
|
||||
}
|
||||
}
|
||||
|
||||
static void assert_same_size(operand left, operand right)
|
||||
{
|
||||
assert(left.operand_size == right.operand_size);
|
||||
}
|
||||
|
||||
static bool is_vector(operand test)
|
||||
{
|
||||
return test.operand_size == 4;
|
||||
}
|
||||
|
||||
static void assert_not_vector(operand test)
|
||||
{
|
||||
assert(!is_vector(test));
|
||||
}
|
||||
|
||||
static void assert_w_or_x(operand test)
|
||||
{
|
||||
assert(test.operand_size == 2 || test.operand_size == 3);
|
||||
}
|
||||
|
||||
static void assert_in_mask(int imm, int bit_count)
|
||||
{
|
||||
assert((imm & ~create_mask(bit_count)) == 0);
|
||||
}
|
||||
|
||||
static void create(rarma_context* result, uint64_t memory_block_size = 1024)
|
||||
{
|
||||
result->memory_block = malloc(memory_block_size);
|
||||
|
||||
result->memory_location = 0;
|
||||
result->memory_block_size = memory_block_size;
|
||||
}
|
||||
|
||||
static void destroy(rarma_context* to_destroy)
|
||||
{
|
||||
free(to_destroy->memory_block);
|
||||
}
|
||||
|
||||
static uint32_t write_instruction(rarma_context* context,uint32_t instruction)
|
||||
{
|
||||
if (context->memory_location >= context->memory_block_size)
|
||||
{
|
||||
std::cout << "RARM OUT OF SPACE" << std::endl;
|
||||
|
||||
throw 0;
|
||||
}
|
||||
|
||||
*(uint32_t*)((uint64_t)context->memory_block + context->memory_location) = instruction;
|
||||
|
||||
context->memory_location += 4;
|
||||
|
||||
return instruction;
|
||||
}
|
||||
|
||||
static int create_mask(int size)
|
||||
{
|
||||
return (1 << size) - 1;
|
||||
}
|
||||
|
||||
static uint32_t add_subtract_shifted(rarma_context* context, bool is_add, bool set_flags, operand d, operand n, operand m, shift_type shift, int imm6)
|
||||
{
|
||||
int sf = d.operand_size == 3;
|
||||
int op = !is_add;
|
||||
int S = set_flags;
|
||||
|
||||
assert_in_mask(imm6, 6);
|
||||
assert_in_mask(shift, 2);
|
||||
|
||||
assert_is_gp_zr(d);
|
||||
assert_is_gp_zr(n);
|
||||
assert_is_gp_zr(m);
|
||||
|
||||
uint32_t result = 0b01011 << 24;
|
||||
|
||||
result |= sf << 31;
|
||||
result |= op << 30;
|
||||
result |= S << 28;
|
||||
result |= shift << 22;
|
||||
result |= m.operand_register_index << 16;
|
||||
result |= imm6 << 10;
|
||||
result |= n.operand_register_index << 5;
|
||||
result |= d.operand_register_index;
|
||||
|
||||
write_instruction(context, result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static uint32_t add_subtract_imm12(rarma_context* context, bool is_add, bool set_flags, operand d, operand n, int imm12)
|
||||
{
|
||||
int sf = d.operand_size == 3;
|
||||
int op = !is_add;
|
||||
int S = set_flags;
|
||||
int sh;
|
||||
|
||||
if (imm12 == 0)
|
||||
{
|
||||
sh = 0;
|
||||
}
|
||||
else if (imm12 & create_mask(12))
|
||||
{
|
||||
assert_in_mask(imm12, 12);
|
||||
|
||||
sh = 0;
|
||||
}
|
||||
else if (imm12 >> 12)
|
||||
{
|
||||
imm12 >>= 12;
|
||||
|
||||
assert((imm12 & ~create_mask(12)) == 0);
|
||||
|
||||
sh = 1;
|
||||
}
|
||||
|
||||
uint32_t result = 0b100010 << 23;
|
||||
|
||||
assert_same_size(d, n);
|
||||
assert_not_vector(d);
|
||||
assert_w_or_x(d);
|
||||
|
||||
assert_is_gp_sp(n);
|
||||
|
||||
if (set_flags)
|
||||
{
|
||||
assert_is_gp_zr(d);
|
||||
}
|
||||
else
|
||||
{
|
||||
assert_is_gp_sp(d);
|
||||
}
|
||||
|
||||
result |= (sf << 31);
|
||||
result |= (op << 30);
|
||||
result |= (S << 29);
|
||||
result |= (sh << 22);
|
||||
|
||||
result |= d.operand_register_index;
|
||||
result |= n.operand_register_index << 5;
|
||||
result |= imm12 << 10;
|
||||
|
||||
write_instruction(context, result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static uint32_t add_imm12(rarma_context* context, operand d, operand n, int imm12)
|
||||
{
|
||||
return add_subtract_imm12(context, true, false, d, n, imm12);
|
||||
}
|
||||
|
||||
static uint32_t sub_imm12(rarma_context* context, operand d, operand n, int imm12)
|
||||
{
|
||||
return add_subtract_imm12(context, false, false, d, n, imm12);
|
||||
}
|
||||
|
||||
static uint32_t adds_imm12(rarma_context* context, operand d, operand n, int imm12)
|
||||
{
|
||||
return add_subtract_imm12(context, true, true, d, n, imm12);
|
||||
}
|
||||
|
||||
static uint32_t subs_imm12(rarma_context* context, operand d, operand n, int imm12)
|
||||
{
|
||||
return add_subtract_imm12(context, false, true, d, n, imm12);
|
||||
}
|
||||
|
||||
static uint32_t add_shifted(rarma_context* context, operand d, operand n, operand m, shift_type shift = shift_type::lsl, int imm6 = 0)
|
||||
{
|
||||
return add_subtract_shifted(context, true, false, d, n, m, shift, imm6);
|
||||
}
|
||||
|
||||
static uint32_t sub_shifted(rarma_context* context, operand d, operand n, operand m, shift_type shift = shift_type::lsl, int imm6 = 0)
|
||||
{
|
||||
return add_subtract_shifted(context, false, false, d, n, m, shift, imm6);
|
||||
}
|
||||
|
||||
static uint32_t adds_shifted(rarma_context* context, operand d, operand n, operand m, shift_type shift = shift_type::lsl, int imm6 = 0)
|
||||
{
|
||||
return add_subtract_shifted(context, true, true, d, n, m, shift, imm6);
|
||||
}
|
||||
|
||||
static uint32_t subs_shifted(rarma_context* context, operand d, operand n, operand m, shift_type shift = shift_type::lsl, int imm6 = 0)
|
||||
{
|
||||
return add_subtract_shifted(context, false, true, d, n, m, shift, imm6);
|
||||
}
|
||||
|
||||
static uint32_t ret(rarma_context* context, operand n)
|
||||
{
|
||||
uint32_t result = 0b1101011001011111000000 << 10;
|
||||
|
||||
assert_is_gp_zr(n);
|
||||
|
||||
result |= n.operand_register_index << 5;
|
||||
|
||||
write_instruction(context, result);
|
||||
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -233,6 +233,15 @@ void assemble_x86_64_code(void** result_code, uint64_t* result_code_size, ir_ope
|
||||
|
||||
case ir_jump_if_equal:
|
||||
case ir_jump_if_not_equal:
|
||||
|
||||
case ir_jump_if_greater_equal_signed:
|
||||
case ir_jump_if_greater_equal_unsigned:
|
||||
case ir_jump_if_greater_signed:
|
||||
case ir_jump_if_greater_unsigned:
|
||||
case ir_jump_if_less_equal_signed:
|
||||
case ir_jump_if_less_equal_unsigned:
|
||||
case ir_jump_if_less_signed:
|
||||
case ir_jump_if_less_unsigned:
|
||||
{
|
||||
ir_operand label_operand = working_operation.sources[0];
|
||||
ir_operand left = working_operation.sources[1];
|
||||
|
||||
+7457
-7457
File diff suppressed because it is too large
Load Diff
+248
-248
File diff suppressed because it is too large
Load Diff
+194
-60
@@ -29,6 +29,7 @@ struct ssa_node
|
||||
std::unordered_set<uint64_t> declared_in_block;
|
||||
std::unordered_map<int, std::unordered_map<uint64_t, uint64_t>> declaration_time_map;
|
||||
std::unordered_map<uint64_t, int> last_declared;
|
||||
std::unordered_map<uint64_t, global_usage_location*> cached_global_declarations;
|
||||
|
||||
std::vector<ssa_node*> inlets;
|
||||
std::vector<ssa_node*> outlets;
|
||||
@@ -196,6 +197,13 @@ static void find_same_register_pools(ssa_node* node)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (in_map(&node->cached_global_declarations, current_source->value))
|
||||
{
|
||||
connect_global_usages(this_global_usage,node->cached_global_declarations[current_source->value]);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
this_global_usage->is_global = true;
|
||||
|
||||
for (auto inlet : node->inlets)
|
||||
@@ -204,6 +212,8 @@ static void find_same_register_pools(ssa_node* node)
|
||||
|
||||
find_register_in_parents(inlet, current_source->value, this_global_usage, &visited);
|
||||
}
|
||||
|
||||
node->cached_global_declarations[current_source->value] = this_global_usage;
|
||||
}
|
||||
|
||||
time++;
|
||||
@@ -544,6 +554,7 @@ static bool optimize_math(ssa_node* working_node)
|
||||
}; break;
|
||||
|
||||
case ir_bitwise_or:
|
||||
case x86_orps:
|
||||
{
|
||||
if (check_constant(src[0], 0))
|
||||
{
|
||||
@@ -571,6 +582,12 @@ static bool optimize_math(ssa_node* working_node)
|
||||
|
||||
convert_to_move(working_operation, ir_operand::create_con(value, des[0].meta_data));
|
||||
|
||||
is_done = false;
|
||||
}
|
||||
else if (ir_operand::are_equal(src[0], src[1]))
|
||||
{
|
||||
convert_to_move(working_operation, src[0]);
|
||||
|
||||
is_done = false;
|
||||
}
|
||||
}; break;
|
||||
@@ -595,6 +612,12 @@ static bool optimize_math(ssa_node* working_node)
|
||||
|
||||
convert_to_move(working_operation, ir_operand::create_con(value, des[0].meta_data));
|
||||
|
||||
is_done = false;
|
||||
}
|
||||
else if (ir_operand::are_equal(src[0], src[1]))
|
||||
{
|
||||
convert_to_move(working_operation, ir_operand::create_con(0));
|
||||
|
||||
is_done = false;
|
||||
}
|
||||
}; break;
|
||||
@@ -620,6 +643,14 @@ static bool optimize_math(ssa_node* working_node)
|
||||
|
||||
is_done = false;
|
||||
}
|
||||
else if (ir_operand::are_equal(src[0], src[1]))
|
||||
{
|
||||
src[1] = ir_operand::create_con(1, src[1].meta_data);
|
||||
|
||||
working_operation->instruction = ir_shift_left;
|
||||
|
||||
is_done = false;
|
||||
}
|
||||
else if (check_constant(src[0]) && check_constant(src[1]))
|
||||
{
|
||||
uint64_t value = src[0].value + src[1].value;
|
||||
@@ -628,6 +659,7 @@ static bool optimize_math(ssa_node* working_node)
|
||||
|
||||
is_done = false;
|
||||
}
|
||||
|
||||
}; break;
|
||||
|
||||
case ir_subtract:
|
||||
@@ -654,6 +686,12 @@ static bool optimize_math(ssa_node* working_node)
|
||||
|
||||
is_done = false;
|
||||
}
|
||||
else if (ir_operand::are_equal(src[0], src[1]))
|
||||
{
|
||||
convert_to_move(working_operation, ir_operand::create_con(0));
|
||||
|
||||
is_done = false;
|
||||
}
|
||||
else if (check_constant(src[0]) && check_constant(src[1]))
|
||||
{
|
||||
uint64_t value = src[0].value - src[1].value;
|
||||
@@ -836,7 +874,7 @@ static void loop_through_operands_find_usage_count(ir_operand* operands, int cou
|
||||
}
|
||||
}
|
||||
|
||||
static bool check_for_register_in_instruction(ir_operand* operands,int count, uint64_t to_check)
|
||||
static bool check_for_register_in_collection(ir_operand* operands,int count, uint64_t to_check)
|
||||
{
|
||||
for (int i = 0; i < count; ++i)
|
||||
{
|
||||
@@ -854,7 +892,7 @@ static bool check_for_register_in_instruction(ir_operand* operands,int count, ui
|
||||
|
||||
static bool check_for_register_in_instruction(ir_operation* operation, uint64_t to_check)
|
||||
{
|
||||
return check_for_register_in_instruction(operation->destinations.data, operation->destinations.count, to_check) | check_for_register_in_instruction(operation->sources.data, operation->sources.count, to_check);
|
||||
return check_for_register_in_collection(operation->destinations.data, operation->destinations.count, to_check) | check_for_register_in_collection(operation->sources.data, operation->sources.count, to_check);
|
||||
}
|
||||
|
||||
void copy_operands(ir_operand* destination,ir_operand* source, int count)
|
||||
@@ -898,10 +936,10 @@ static bool optimize_multiple_instructions(ssa_node* working_node)
|
||||
|
||||
loop_through_operands_find_usage_count(working_operation->sources.data, working_operation->sources.count, &usage_count);
|
||||
|
||||
if (working_operation->destinations.count != 1)
|
||||
continue;
|
||||
|
||||
declaration_location[working_operation->destinations[0].value] = working_operation;
|
||||
for (int r = 0; r < working_operation->destinations.count; ++r)
|
||||
{
|
||||
declaration_location[working_operation->destinations[r].value] = working_operation;
|
||||
}
|
||||
}
|
||||
|
||||
time = 0;
|
||||
@@ -1081,9 +1119,28 @@ static bool optimize_multiple_instructions(ssa_node* working_node)
|
||||
|
||||
is_done = false;
|
||||
}; break;
|
||||
|
||||
case ir_compare_greater_equal_unsigned:
|
||||
{
|
||||
replace_jump_with_condition(ir, label, working_operation, condition_source, ir_jump_if_greater_equal_unsigned);
|
||||
|
||||
is_done = false;
|
||||
}; break;
|
||||
|
||||
case ir_compare_greater_equal_signed:
|
||||
{
|
||||
replace_jump_with_condition(ir, label, working_operation, condition_source, ir_jump_if_greater_equal_signed);
|
||||
|
||||
is_done = false;
|
||||
}; break;
|
||||
|
||||
default:
|
||||
break;
|
||||
{
|
||||
if (ir_operation_block::is_compare(condition_source))
|
||||
{
|
||||
std::cout << instruction_names[condition_source->instruction] << std::endl;
|
||||
}
|
||||
}; break;
|
||||
}
|
||||
|
||||
}; break;
|
||||
@@ -1096,70 +1153,143 @@ static bool optimize_multiple_instructions(ssa_node* working_node)
|
||||
if (ir_operand::is_constant(&source_operand))
|
||||
continue;
|
||||
|
||||
if (!is_global(context, destination_operand))
|
||||
continue;
|
||||
|
||||
if (is_global(context, source_operand))
|
||||
continue;
|
||||
|
||||
ir_operation* local_declared_operation = declaration_location[source_operand.value];
|
||||
|
||||
if (local_declared_operation == nullptr)
|
||||
continue;
|
||||
|
||||
if (usage_count[source_operand.value] > 1)
|
||||
continue;
|
||||
|
||||
if (local_declared_operation->destinations.count == 0)
|
||||
continue;
|
||||
|
||||
bool is_valid = true;
|
||||
|
||||
for (auto b = i->prev; b != raw_node->entry_instruction->prev; b = b->prev)
|
||||
if (is_global(context, destination_operand) && !is_global(context, source_operand))
|
||||
{
|
||||
ir_operation* check_operation = &b->data;
|
||||
ir_operation* local_declared_operation = declaration_location[source_operand.value];
|
||||
|
||||
if (check_operation == local_declared_operation)
|
||||
break;
|
||||
|
||||
if (check_for_register_in_instruction(check_operation, destination_operand.value))
|
||||
if (local_declared_operation == nullptr)
|
||||
continue;
|
||||
|
||||
if (usage_count[source_operand.value] > 1)
|
||||
continue;
|
||||
|
||||
if (local_declared_operation->destinations.count == 0)
|
||||
continue;
|
||||
|
||||
bool is_valid = true;
|
||||
|
||||
for (auto b = i->prev; b != raw_node->entry_instruction->prev; b = b->prev)
|
||||
{
|
||||
is_valid = false;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_valid)
|
||||
continue;
|
||||
|
||||
for (int o = 0; o < local_declared_operation->destinations.count; ++o)
|
||||
{
|
||||
ir_operand* replace_candidate = &local_declared_operation->destinations.data[o];
|
||||
|
||||
if (replace_candidate->value == source_operand.value)
|
||||
{
|
||||
if (replace_candidate->meta_data != source_operand.meta_data)
|
||||
ir_operation* check_operation = &b->data;
|
||||
|
||||
if (check_operation == local_declared_operation)
|
||||
break;
|
||||
|
||||
if (check_for_register_in_instruction(check_operation, destination_operand.value))
|
||||
{
|
||||
//is_valid = false;
|
||||
is_valid = false;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_valid)
|
||||
continue;
|
||||
|
||||
for (int o = 0; o < local_declared_operation->destinations.count; ++o)
|
||||
{
|
||||
ir_operand* replace_candidate = &local_declared_operation->destinations.data[o];
|
||||
|
||||
if (replace_candidate->value == source_operand.value)
|
||||
{
|
||||
if (replace_candidate->meta_data != source_operand.meta_data)
|
||||
{
|
||||
//is_valid = false;
|
||||
|
||||
//IN A LOT OF CACES, THIS CAN BE IGNORED
|
||||
//TODO, FIND THOSE CASES
|
||||
|
||||
//break;
|
||||
}
|
||||
|
||||
replace_candidate->value = destination_operand.value;
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_valid)
|
||||
continue;
|
||||
|
||||
nop_operation(working_operation);
|
||||
|
||||
is_done = false;
|
||||
}
|
||||
else if (!is_global(context,destination_operand) && is_global(context, source_operand))
|
||||
{
|
||||
bool is_zero_extend = false;
|
||||
bool ignore = false;
|
||||
|
||||
//IN A LOT OF CACES, THIS CAN BE IGNORED
|
||||
//TODO, FIND THOSE CASES
|
||||
std::vector<ir_operand*> to_replace;
|
||||
intrusive_linked_list_element<ir_operation>* look_next = nullptr;
|
||||
|
||||
//break;
|
||||
for (auto check = i->next; check != raw_node->final_instruction->next; check = check->next)
|
||||
{
|
||||
ir_operation* check_operation = &check->data;
|
||||
|
||||
if (check_if_zero_extend(&check->data,destination_operand))
|
||||
{
|
||||
is_zero_extend = true;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
replace_candidate->value = destination_operand.value;
|
||||
for (int o = 0; o < check_operation->sources.count; ++o)
|
||||
{
|
||||
ir_operand* to_replace_candidate = &check_operation->sources[o];
|
||||
|
||||
if (ir_operand::is_constant(to_replace_candidate))
|
||||
continue;
|
||||
|
||||
if (to_replace_candidate->value != destination_operand.value)
|
||||
continue;
|
||||
|
||||
to_replace.push_back(to_replace_candidate);
|
||||
}
|
||||
|
||||
if (check_for_register_in_collection(check_operation->destinations.data, check_operation->destinations.count, source_operand.value))
|
||||
{
|
||||
look_next = check->next;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (look_next != nullptr)
|
||||
{
|
||||
for (auto check = look_next; check != raw_node->final_instruction->next; check = check->next)
|
||||
{
|
||||
ir_operation* check_operation = &check->data;
|
||||
|
||||
if (!check_for_register_in_collection(check_operation->sources.data, check_operation->sources.count, destination_operand.value))
|
||||
continue;
|
||||
|
||||
ignore = true;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ignore)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (is_zero_extend)
|
||||
{
|
||||
i->data.instruction = ir_zero_extend;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
for (auto i : to_replace)
|
||||
{
|
||||
i->value = source_operand.value;
|
||||
}
|
||||
|
||||
nop_operation(working_operation);
|
||||
|
||||
is_done = false;
|
||||
}
|
||||
|
||||
if (!is_valid)
|
||||
continue;
|
||||
|
||||
nop_operation(working_operation);
|
||||
|
||||
is_done = false;
|
||||
|
||||
}; break;
|
||||
|
||||
default:
|
||||
@@ -1269,6 +1399,10 @@ void convert_to_ssa(ir_operation_block* ir, bool optimize)
|
||||
}
|
||||
}
|
||||
|
||||
//ir_operation_block::log(ssa.ir);
|
||||
|
||||
//std::cin.get();
|
||||
|
||||
linier_scan_register_allocator_pass(ssa.cfg);
|
||||
|
||||
destroy_ssa_context(&ssa);
|
||||
|
||||
@@ -49,9 +49,11 @@ static void unmark_memory_executable(void* memory, uint64_t size)
|
||||
|
||||
static uint64_t align_64_kb(uint64_t source)
|
||||
{
|
||||
uint64_t mask = ~63ULL;
|
||||
uint64_t page_size = 64 * 1024;
|
||||
|
||||
return (source & mask) + 64;
|
||||
uint64_t mask = page_size - 1;
|
||||
|
||||
return (source & ~mask) + page_size;
|
||||
}
|
||||
|
||||
bool jit_memory::create(jit_memory** result, uint64_t allocation_size, abi host_abi)
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"folders": [
|
||||
{
|
||||
"path": "../../../rem_tester_arm"
|
||||
},
|
||||
{
|
||||
"path": "../.."
|
||||
}
|
||||
],
|
||||
"settings": {}
|
||||
}
|
||||
Reference in New Issue
Block a user