Super Mario Odyssey playable!

Super Mario Odyssey is playable using rem emulator in Ryujinx with full implementation.
This commit is contained in:
Mphatso Raymond Mataka
2025-01-12 03:30:33 -08:00
parent 2496079422
commit aa0bbc166f
8 changed files with 1703 additions and 4 deletions
+53 -3
View File
@@ -103,8 +103,10 @@ void assemble_x86_64_code(void** result_code, uint64_t* result_code_size, ir_ope
{
arena_allocator* allocator = source_ir->allocator;
*result_code = arena_allocator::allocate_recursive(allocator, ONE_MB);
Xbyak::CodeGenerator c(ONE_MB, *result_code);
int buffer_size = ONE_MB * 5;
*result_code = arena_allocator::allocate_recursive(allocator, buffer_size);
Xbyak::CodeGenerator c(buffer_size, *result_code);
c.setDefaultJmpNEAR(true);
@@ -113,6 +115,11 @@ void assemble_x86_64_code(void** result_code, uint64_t* result_code_size, ir_ope
ir_operation working_operation = i->data;
ir_instructions instruction = (ir_instructions)working_operation.instruction;
if (c.getSize() > buffer_size - 1024)
{
throw_error();
}
switch (instruction)
{
case ir_negate: c.neg(create_operand(working_operation.destinations[0])); assert_valid_unary_operation(&working_operation); break;
@@ -138,7 +145,6 @@ void assemble_x86_64_code(void** result_code, uint64_t* result_code_size, ir_ope
case ir_external_call:
{
auto function_to_call = create_operand(working_operation.sources[0]);
int caller_size = 120;
c.sub(c.rsp, caller_size);
@@ -755,6 +761,50 @@ void assemble_x86_64_code(void** result_code, uint64_t* result_code_size, ir_ope
case x86_subsd: assert_valid_binary_float_operation(&working_operation); c.subsd(create_operand<Xbyak::Xmm>(working_operation.destinations[0]), create_operand<Xbyak::Xmm>(working_operation.sources[1])); break;
case x86_subss: assert_valid_binary_float_operation(&working_operation); c.subss(create_operand<Xbyak::Xmm>(working_operation.destinations[0]), create_operand<Xbyak::Xmm>(working_operation.sources[1])); 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 ir_floating_point_compare_equal:
case ir_floating_point_compare_less:
case ir_floating_point_compare_not_equal:
case ir_floating_point_compare_greater:
case ir_floating_point_compare_greater_equal:
{
ir_operand destination = working_operation.destinations[0];
ir_operand source_0 = working_operation.sources[0];
ir_operand source_1 = working_operation.sources[1];
assert(!ir_operand::is_vector(&destination));
assert(ir_operand::is_vector(&source_0));
assert(ir_operand::is_vector(&source_1));
switch (ir_operand::get_raw_size(&destination))
{
case int32:
{
c.comiss(create_operand<Xbyak::Xmm>(source_0), create_operand<Xbyak::Xmm>(source_1));
}; break;
case int64:
{
c.comisd(create_operand<Xbyak::Xmm>(source_0), create_operand<Xbyak::Xmm>(source_1));
}; break;
default: throw_error();
}
switch (instruction)
{
case ir_floating_point_compare_equal: c.sete(create_operand<Xbyak::Reg8>(destination)); break;
case ir_floating_point_compare_not_equal: c.setne(create_operand<Xbyak::Reg8>(destination)); break;
case ir_floating_point_compare_less: c.setb(create_operand<Xbyak::Reg8>(destination)); break;
case ir_floating_point_compare_greater: c.seta(create_operand<Xbyak::Reg8>(destination)); break;
case ir_floating_point_compare_greater_equal: c.setae(create_operand<Xbyak::Reg8>(destination)); break;
default: throw_error();
}
c.and_(create_operand<Xbyak::Reg64>(destination), 1);
}; break;
default:
{
std::cout << "UNDEFINED X86 INSTRUCTION " << std::endl;
+107
View File
@@ -77,6 +77,16 @@ static ir_operand register_or_constant(x86_pre_allocator_context* context, ir_op
return register_or_constant(context, &source, force_copy);
}
static ir_operand vector_from_register(x86_pre_allocator_context* context, ir_operand source)
{
source = register_or_constant(context, source);
ir_operand result = create_scrap_operand(context, int128);
ir_operation_block::emitds(context->ir, x86_movq_to_vec, result, source);
return result;
}
static void emit_throw_exception(x86_pre_allocator_context* context)
{
ir_operand zero = register_or_constant(context, ir_operand::create_con(0));
@@ -181,6 +191,70 @@ static void emit_d_n_f_d_n_m(x86_pre_allocator_context* result, uint64_t instruc
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)
{
assert_same_size({ destination, source_0, source_1 });
ir_operand working_destination = destination;
ir_operand working_vector_0 = vector_from_register(result, source_0);
ir_operand working_vector_1 = vector_from_register(result, source_1);
ir_operation_block::emitds(result->ir, instruction, working_destination, working_vector_0, working_vector_1);
}
static void emit_floating_point_binary(x86_pre_allocator_context* result, uint64_t instruction, ir_operand destination, ir_operand source_0, ir_operand source_1)
{
assert_same_size({ destination, 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_vector_0 = vector_from_register(result, working_source_0);
ir_operand working_vector_1 = vector_from_register(result, working_source_1);
int working_instruction;
switch (instruction)
{
case ir_floating_point_add: working_instruction = ir_operand::get_raw_size(&destination) == int64 ? x86_addsd : x86_addss; break;
case ir_floating_point_subtract: working_instruction = ir_operand::get_raw_size(&destination) == int64 ? x86_subsd : x86_subss; break;
case ir_floating_point_multiply: working_instruction = ir_operand::get_raw_size(&destination) == int64 ? x86_mulsd : x86_mulss; break;
case ir_floating_point_divide: working_instruction = ir_operand::get_raw_size(&destination) == int64 ? x86_divsd : x86_divss; break;
case ir_floating_point_select_min: working_instruction = ir_operand::get_raw_size(&destination) == int64 ? x86_minsd : x86_minss; break;
case ir_floating_point_select_max: working_instruction = ir_operand::get_raw_size(&destination) == int64 ? x86_maxsd : x86_maxss; break;
default: throw_error();
}
ir_operation_block::emitds(result->ir, working_instruction, working_vector_0, working_vector_0, working_vector_1);
ir_operation_block::emitds(result->ir, x86_movq_to_gp, working_destination, working_vector_0);
}
static void emit_floating_point_unary(x86_pre_allocator_context* result, uint64_t instruction, ir_operand destination, ir_operand source_0)
{
assert_same_size({ destination, source_0 });
ir_operand working_destination = destination;
ir_operand working_source_0 = register_or_constant(result, &source_0);
ir_operand working_vector_0 = vector_from_register(result, working_source_0);
int working_instruction;
switch (instruction)
{
case ir_floating_point_square_root: working_instruction = ir_operand::get_raw_size(&destination) == int64 ? x86_sqrtsd : x86_sqrtss; break;
default: throw_error();
}
ir_operation_block::emitds(result->ir, working_instruction, working_vector_0, working_vector_0);
ir_operation_block::emitds(result->ir, x86_movq_to_gp, working_destination, working_vector_0);
}
static void emit_compare(x86_pre_allocator_context* result, uint64_t instruction, ir_operand destination, ir_operand source_0, ir_operand source_1)
{
assert_same_size({ destination, source_0, source_1 });
@@ -635,6 +709,31 @@ static void emit_pre_allocation_instruction(x86_pre_allocator_context* pre_alloc
emit_d_n_f_d_n_m(pre_allocator_context, operation->instruction, operation->destinations[0], operation->sources[0], operation->sources[1]);
}; break;
case ir_floating_point_add:
case ir_floating_point_subtract:
case ir_floating_point_multiply:
case ir_floating_point_divide:
case ir_floating_point_select_min:
case ir_floating_point_select_max:
{
assert_operand_count(operation, 1, 2);
assert_is_register(operation->destinations[0]);
emit_floating_point_binary(pre_allocator_context, operation->instruction, operation->destinations[0], operation->sources[0], operation->sources[1]);
}; break;
case ir_floating_point_compare_equal:
case ir_floating_point_compare_less:
case ir_floating_point_compare_not_equal:
case ir_floating_point_compare_greater:
case ir_floating_point_compare_greater_equal:
{
assert_operand_count(operation, 1, 2);
assert_is_register(operation->destinations[0]);
emit_floating_point_compare(pre_allocator_context, operation->instruction, operation->destinations[0], operation->sources[0], operation->sources[1]);
}; break;
case ir_multiply_hi_signed:
case ir_multiply_hi_unsigned:
case ir_divide_unsigned:
@@ -715,6 +814,14 @@ static void emit_pre_allocation_instruction(x86_pre_allocator_context* pre_alloc
}; break;
case ir_floating_point_square_root:
{
assert_operand_count(operation, 1, 1);
assert_is_register(operation->destinations[0]);
emit_floating_point_unary(pre_allocator_context, operation->instruction, operation->destinations[0], operation->sources[0]);
}; break;
case ir_sign_extend:
{
assert_operand_count(operation, 1, 1);
@@ -183,4 +183,15 @@ uint64_t call_counter_interpreter(interpreter_data* ctx)
uint64_t call_interpreter(interpreter_data* ctx, uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5, uint64_t function)
{
return ((uint64_t(*)(uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t))function)(a0, a1, a2, a3, a4, a5);
}
//Optimize
uint64_t use_fast_float_interpreter(interpreter_data* ctx)
{
return false;
}
uint64_t use_x86_sse(interpreter_data* ctx)
{
return false;
}
@@ -221,4 +221,15 @@ ir_operand call_jit(ssa_emit_context* ctx, ir_operand a0, ir_operand a1, ir_oper
ir_operation_block::emitds(ctx->ir, ir_external_call, result, ir_operand::create_con(function), a0, a1, a2, a3, a4, a5);
return result;
}
//Optimization
uint64_t use_fast_float_jit(ssa_emit_context* ctx)
{
return 1;
}
uint64_t use_x86_sse(ssa_emit_context* ctx)
{
return 1;
}
File diff suppressed because it is too large Load Diff
+57
View File
@@ -66,6 +66,32 @@ uint64_t convert_to_float(uint64_t source, bool is_signed)
return *(uint64_t*)&temp;
}
template <typename T>
double get_float(uint64_t source)
{
switch (sizeof(T))
{
case 4: return convert<float, uint32_t>(source);
case 8: return convert<double, uint64_t>(source);
default: throw_error();
}
}
template <typename T>
uint64_t get_int(double source)
{
switch (sizeof(T))
{
case 4: return convert<uint32_t, float>(source);
case 8: return convert<uint64_t, double>(source);
}
}
static uint64_t undefined_value()
{
throw_error();
}
//INTERPRETER
uint64_t sign_extend_interpreter(interpreter_data* ctx, uint64_t source, uint64_t count);
template <typename O>
@@ -108,6 +134,12 @@ uint128_t replicate_vector_interpreter(interpreter_data* ctx, uint128_t source,
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);
uint64_t float_imm_interpreter(interpreter_data* ctx, uint64_t source, uint64_t N);
template <typename F>
F create_fixed_from_fbits_interpreter(interpreter_data* ctx, uint64_t fbits, uint64_t N);
uint64_t FPAdd_interpreter(interpreter_data* ctx, uint64_t operand1, uint64_t operand2, uint64_t FPCR, uint64_t N);
uint64_t FPSub_interpreter(interpreter_data* ctx, uint64_t operand1, uint64_t operand2, uint64_t FPCR, uint64_t N);
uint64_t FPMul_interpreter(interpreter_data* ctx, uint64_t operand1, uint64_t operand2, uint64_t FPCR, uint64_t N);
@@ -118,6 +150,7 @@ uint64_t FPMaxNum_interpreter(interpreter_data* ctx, uint64_t operand1, uint64_t
uint64_t FPMinNum_interpreter(interpreter_data* ctx, uint64_t operand1, uint64_t operand2, uint64_t FPCR, uint64_t N);
uint64_t FPCompare_interpreter(interpreter_data* ctx, uint64_t operand1, uint64_t operand2, uint64_t FPCR, uint64_t N);
uint64_t FPRSqrtStepFused_interpreter(interpreter_data* ctx, uint64_t operand1, uint64_t operand2, uint64_t FPCR, uint64_t N);
uint64_t FPRecipStepFused_interpreter(interpreter_data* ctx, uint64_t operand1, uint64_t operand2, uint64_t FPCR, uint64_t N);
uint64_t FPCompareEQ_interpreter(interpreter_data* ctx, uint64_t operand1, uint64_t operand2, uint64_t FPCR, uint64_t N);
uint64_t FPCompareGT_interpreter(interpreter_data* ctx, uint64_t operand1, uint64_t operand2, uint64_t FPCR, uint64_t N);
uint64_t FPCompareGE_interpreter(interpreter_data* ctx, uint64_t operand1, uint64_t operand2, uint64_t FPCR, uint64_t N);
@@ -125,6 +158,7 @@ uint64_t FPSqrt_interpreter(interpreter_data* ctx, uint64_t operand, uint64_t FP
uint64_t FPNeg_interpreter(interpreter_data* ctx, uint64_t operand, uint64_t FPCR, uint64_t N);
uint64_t FPAbs_interpreter(interpreter_data* ctx, uint64_t operand, uint64_t FPCR, uint64_t N);
uint64_t FPRSqrtEstimate_interpreter(interpreter_data* ctx, uint64_t operand, uint64_t FPCR, uint64_t N);
uint64_t FPRecipEstimate_interpreter(interpreter_data* ctx, uint64_t operand, uint64_t FPCR, uint64_t N);
uint64_t FixedToFP_interpreter(interpreter_data* ctx, uint64_t source, uint64_t fracbits, uint64_t is_unsigned, uint64_t to, uint64_t from);
uint64_t FPToFixed_interpreter(interpreter_data* ctx, uint64_t source, uint64_t fracbits, uint64_t is_unsigned, uint64_t round, uint64_t to, uint64_t from);
uint64_t FPConvert_interpreter(interpreter_data* ctx, uint64_t source, uint64_t to, uint64_t from);
@@ -202,6 +236,7 @@ void conversion_between_floating_point_and_fixed_point_interpreter(interpreter_d
void shl_immedaite_interpreter(interpreter_data* ctx, uint64_t Q, uint64_t immh, uint64_t immb, uint64_t Rn, uint64_t Rd);
void sshr_vector_interpreter(interpreter_data* ctx, uint64_t Q, uint64_t immh, uint64_t immb, uint64_t Rn, uint64_t Rd);
void shll_shll2_interpreter(interpreter_data* ctx, uint64_t Q, uint64_t U, uint64_t immh, uint64_t immb, uint64_t Rn, uint64_t Rd);
void shrn_interpreter(interpreter_data* ctx, uint64_t Q, uint64_t immh, uint64_t immb, uint64_t Rn, uint64_t Rd);
void rev64_vector_interpreter(interpreter_data* ctx, uint64_t Q, uint64_t size, uint64_t Rn, uint64_t Rd);
void neg_vector_interpreter(interpreter_data* ctx, uint64_t Q, uint64_t size, uint64_t Rn, uint64_t Rd);
void not_vector_interpreter(interpreter_data* ctx, uint64_t Q, uint64_t Rn, uint64_t Rd);
@@ -220,6 +255,7 @@ void and_bic_vector_interpreter(interpreter_data* ctx, uint64_t Q, uint64_t inve
void eor_vector_interpreter(interpreter_data* ctx, uint64_t Q, uint64_t Rm, uint64_t Rn, uint64_t Rd);
void xnt_xnt2_interpreter(interpreter_data* ctx, uint64_t Q, uint64_t size, uint64_t Rn, uint64_t Rd);
void zip_interpreter(interpreter_data* ctx, uint64_t Q, uint64_t size, uint64_t Rm, uint64_t op, uint64_t Rn, uint64_t Rd);
void trn_interpreter(interpreter_data* ctx, uint64_t Q, uint64_t size, uint64_t Rm, uint64_t op, uint64_t Rn, uint64_t Rd);
void tbl_interpreter(interpreter_data* ctx, uint64_t Q, uint64_t Rm, uint64_t len, uint64_t Rn, uint64_t Rd);
void ld1r_no_offset_interpreter(interpreter_data* ctx, uint64_t Q, uint64_t size, uint64_t Rn, uint64_t Rt);
void ld1r_post_index_interpreter(interpreter_data* ctx, uint64_t Q, uint64_t Rm, uint64_t size, uint64_t Rn, uint64_t Rt);
@@ -240,8 +276,10 @@ void fmov_scalar_immediate_interpreter(interpreter_data* ctx, uint64_t ftype, ui
void fcvt_interpreter(interpreter_data* ctx, uint64_t ftype, uint64_t opc, uint64_t Rn, uint64_t Rd);
void fabs_scalar_interpreter(interpreter_data* ctx, uint64_t ftype, uint64_t Rn, uint64_t Rd);
void fneg_scalar_interpreter(interpreter_data* ctx, uint64_t ftype, uint64_t Rn, uint64_t Rd);
void fneg_vector_interpreter(interpreter_data* ctx, uint64_t Q, uint64_t sz, uint64_t Rn, uint64_t Rd);
void fsqrt_scalar_interpreter(interpreter_data* ctx, uint64_t ftype, uint64_t Rn, uint64_t Rd);
void fsqrt_vector_interpreter(interpreter_data* ctx, uint64_t Q, uint64_t sz, uint64_t Rn, uint64_t Rd);
void frecpe_vector_interpreter(interpreter_data* ctx, uint64_t Q, uint64_t sz, 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);
void fcvtz_scalar_integer_interpreter(interpreter_data* ctx, uint64_t sf, uint64_t ftype, uint64_t U, uint64_t Rn, uint64_t Rd);
@@ -257,6 +295,7 @@ void faddp_vector_interpreter(interpreter_data* ctx, uint64_t Q, uint64_t sz, ui
void frsqrte_scalar_interpreter(interpreter_data* ctx, uint64_t sz, uint64_t Rn, uint64_t Rd);
void frsqrte_vector_interpreter(interpreter_data* ctx, uint64_t Q, uint64_t sz, uint64_t Rn, uint64_t Rd);
void frsqrts_vector_interpreter(interpreter_data* ctx, uint64_t Q, uint64_t sz, uint64_t Rm, uint64_t Rn, uint64_t Rd);
void frecps_vector_interpreter(interpreter_data* ctx, uint64_t Q, uint64_t sz, uint64_t Rm, uint64_t Rn, uint64_t Rd);
void fmul_scalar_by_element_interpreter(interpreter_data* ctx, uint64_t sz, uint64_t L, uint64_t M, uint64_t Rm, uint64_t H, uint64_t Rn, uint64_t Rd);
void fmul_vector_by_element_interpreter(interpreter_data* ctx, uint64_t Q, uint64_t sz, uint64_t L, uint64_t M, uint64_t Rm, uint64_t H, uint64_t Rn, uint64_t Rd);
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);
@@ -265,6 +304,7 @@ void frint_interpreter(interpreter_data* ctx, uint64_t ftype, uint64_t Rn, uint6
void frintp_scalar_interpreter(interpreter_data* ctx, uint64_t ftype, uint64_t Rn, uint64_t Rd);
void frintm_scalar_interpreter(interpreter_data* ctx, uint64_t ftype, uint64_t Rn, uint64_t Rd);
void fcvtp_scalar_integer_interpreter(interpreter_data* ctx, uint64_t sf, uint64_t ftype, uint64_t U, uint64_t Rn, uint64_t Rd);
void faddp_scalar_interpreter(interpreter_data* ctx, uint64_t sz, uint64_t Rn, uint64_t Rd);
uint64_t _x_interpreter(interpreter_data* ctx, uint64_t reg_id);//THIS FUNCTION IS USER DEFINED
void _x_interpreter(interpreter_data* ctx, uint64_t reg_id, uint64_t value);//THIS FUNCTION IS USER DEFINED
uint64_t _sys_interpreter(interpreter_data* ctx, uint64_t reg_id);//THIS FUNCTION IS USER DEFINED
@@ -277,6 +317,8 @@ void _branch_conditional_interpreter(interpreter_data* ctx, uint64_t yes, uint64
uint64_t get_vector_context_interpreter(interpreter_data* ctx);//THIS FUNCTION IS USER DEFINED
void store_context_interpreter(interpreter_data* ctx);//THIS FUNCTION IS USER DEFINED
void load_context_interpreter(interpreter_data* ctx);//THIS FUNCTION IS USER DEFINED
uint64_t use_fast_float_interpreter(interpreter_data* ctx);//THIS FUNCTION IS USER DEFINED
uint64_t use_x86_sse_interpreter(interpreter_data* ctx);//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
@@ -322,6 +364,11 @@ ir_operand replicate_vector_jit(ssa_emit_context* ctx, ir_operand source, uint64
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);
ir_operand float_imm_jit(ssa_emit_context* ctx, ir_operand source, uint64_t N);
ir_operand create_fixed_from_fbits_jit(ssa_emit_context* ctx,uint64_t F, uint64_t fbits, uint64_t N);
ir_operand FPAdd_jit(ssa_emit_context* ctx, ir_operand operand1, ir_operand operand2, ir_operand FPCR, uint64_t N);
ir_operand FPSub_jit(ssa_emit_context* ctx, ir_operand operand1, ir_operand operand2, ir_operand FPCR, uint64_t N);
ir_operand FPMul_jit(ssa_emit_context* ctx, ir_operand operand1, ir_operand operand2, ir_operand FPCR, uint64_t N);
@@ -332,6 +379,7 @@ ir_operand FPMaxNum_jit(ssa_emit_context* ctx, ir_operand operand1, ir_operand o
ir_operand FPMinNum_jit(ssa_emit_context* ctx, ir_operand operand1, ir_operand operand2, ir_operand FPCR, uint64_t N);
ir_operand FPCompare_jit(ssa_emit_context* ctx, ir_operand operand1, ir_operand operand2, ir_operand FPCR, uint64_t N);
ir_operand FPRSqrtStepFused_jit(ssa_emit_context* ctx, ir_operand operand1, ir_operand operand2, ir_operand FPCR, uint64_t N);
ir_operand FPRecipStepFused_jit(ssa_emit_context* ctx, ir_operand operand1, ir_operand operand2, ir_operand FPCR, uint64_t N);
ir_operand FPCompareEQ_jit(ssa_emit_context* ctx, ir_operand operand1, ir_operand operand2, ir_operand FPCR, uint64_t N);
ir_operand FPCompareGT_jit(ssa_emit_context* ctx, ir_operand operand1, ir_operand operand2, ir_operand FPCR, uint64_t N);
ir_operand FPCompareGE_jit(ssa_emit_context* ctx, ir_operand operand1, ir_operand operand2, ir_operand FPCR, uint64_t N);
@@ -339,6 +387,7 @@ ir_operand FPSqrt_jit(ssa_emit_context* ctx, ir_operand operand, ir_operand FPCR
ir_operand FPNeg_jit(ssa_emit_context* ctx, ir_operand operand, ir_operand FPCR, uint64_t N);
ir_operand FPAbs_jit(ssa_emit_context* ctx, ir_operand operand, ir_operand FPCR, uint64_t N);
ir_operand FPRSqrtEstimate_jit(ssa_emit_context* ctx, ir_operand operand, ir_operand FPCR, uint64_t N);
ir_operand FPRecipEstimate_jit(ssa_emit_context* ctx, ir_operand operand, ir_operand FPCR, uint64_t N);
ir_operand FixedToFP_jit(ssa_emit_context* ctx, ir_operand source, uint64_t fracbits, uint64_t is_unsigned, uint64_t to, uint64_t from);
ir_operand FPToFixed_jit(ssa_emit_context* ctx, ir_operand source, uint64_t fracbits, uint64_t is_unsigned, uint64_t round, uint64_t to, uint64_t from);
ir_operand FPConvert_jit(ssa_emit_context* ctx, ir_operand source, uint64_t to, uint64_t from);
@@ -414,6 +463,7 @@ void conversion_between_floating_point_and_fixed_point_jit(ssa_emit_context* ctx
void shl_immedaite_jit(ssa_emit_context* ctx, uint64_t Q, uint64_t immh, uint64_t immb, uint64_t Rn, uint64_t Rd);
void sshr_vector_jit(ssa_emit_context* ctx, uint64_t Q, uint64_t immh, uint64_t immb, uint64_t Rn, uint64_t Rd);
void shll_shll2_jit(ssa_emit_context* ctx, uint64_t Q, uint64_t U, uint64_t immh, uint64_t immb, uint64_t Rn, uint64_t Rd);
void shrn_jit(ssa_emit_context* ctx, uint64_t Q, uint64_t immh, uint64_t immb, uint64_t Rn, uint64_t Rd);
void rev64_vector_jit(ssa_emit_context* ctx, uint64_t Q, uint64_t size, uint64_t Rn, uint64_t Rd);
void neg_vector_jit(ssa_emit_context* ctx, uint64_t Q, uint64_t size, uint64_t Rn, uint64_t Rd);
void not_vector_jit(ssa_emit_context* ctx, uint64_t Q, uint64_t Rn, uint64_t Rd);
@@ -432,6 +482,7 @@ void and_bic_vector_jit(ssa_emit_context* ctx, uint64_t Q, uint64_t invert, uint
void eor_vector_jit(ssa_emit_context* ctx, uint64_t Q, uint64_t Rm, uint64_t Rn, uint64_t Rd);
void xnt_xnt2_jit(ssa_emit_context* ctx, uint64_t Q, uint64_t size, uint64_t Rn, uint64_t Rd);
void zip_jit(ssa_emit_context* ctx, uint64_t Q, uint64_t size, uint64_t Rm, uint64_t op, uint64_t Rn, uint64_t Rd);
void trn_jit(ssa_emit_context* ctx, uint64_t Q, uint64_t size, uint64_t Rm, uint64_t op, uint64_t Rn, uint64_t Rd);
void tbl_jit(ssa_emit_context* ctx, uint64_t Q, uint64_t Rm, uint64_t len, uint64_t Rn, uint64_t Rd);
void ld1r_no_offset_jit(ssa_emit_context* ctx, uint64_t Q, uint64_t size, uint64_t Rn, uint64_t Rt);
void ld1r_post_index_jit(ssa_emit_context* ctx, uint64_t Q, uint64_t Rm, uint64_t size, uint64_t Rn, uint64_t Rt);
@@ -452,8 +503,10 @@ void fmov_scalar_immediate_jit(ssa_emit_context* ctx, uint64_t ftype, uint64_t i
void fcvt_jit(ssa_emit_context* ctx, uint64_t ftype, uint64_t opc, uint64_t Rn, uint64_t Rd);
void fabs_scalar_jit(ssa_emit_context* ctx, uint64_t ftype, uint64_t Rn, uint64_t Rd);
void fneg_scalar_jit(ssa_emit_context* ctx, uint64_t ftype, uint64_t Rn, uint64_t Rd);
void fneg_vector_jit(ssa_emit_context* ctx, uint64_t Q, uint64_t sz, uint64_t Rn, uint64_t Rd);
void fsqrt_scalar_jit(ssa_emit_context* ctx, uint64_t ftype, uint64_t Rn, uint64_t Rd);
void fsqrt_vector_jit(ssa_emit_context* ctx, uint64_t Q, uint64_t sz, uint64_t Rn, uint64_t Rd);
void frecpe_vector_jit(ssa_emit_context* ctx, uint64_t Q, uint64_t sz, 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);
void fcvtz_scalar_integer_jit(ssa_emit_context* ctx, uint64_t sf, uint64_t ftype, uint64_t U, uint64_t Rn, uint64_t Rd);
@@ -469,6 +522,7 @@ void faddp_vector_jit(ssa_emit_context* ctx, uint64_t Q, uint64_t sz, uint64_t R
void frsqrte_scalar_jit(ssa_emit_context* ctx, uint64_t sz, uint64_t Rn, uint64_t Rd);
void frsqrte_vector_jit(ssa_emit_context* ctx, uint64_t Q, uint64_t sz, uint64_t Rn, uint64_t Rd);
void frsqrts_vector_jit(ssa_emit_context* ctx, uint64_t Q, uint64_t sz, uint64_t Rm, uint64_t Rn, uint64_t Rd);
void frecps_vector_jit(ssa_emit_context* ctx, uint64_t Q, uint64_t sz, uint64_t Rm, uint64_t Rn, uint64_t Rd);
void fmul_scalar_by_element_jit(ssa_emit_context* ctx, uint64_t sz, uint64_t L, uint64_t M, uint64_t Rm, uint64_t H, uint64_t Rn, uint64_t Rd);
void fmul_vector_by_element_jit(ssa_emit_context* ctx, uint64_t Q, uint64_t sz, uint64_t L, uint64_t M, uint64_t Rm, uint64_t H, uint64_t Rn, uint64_t Rd);
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);
@@ -477,6 +531,7 @@ void frint_jit(ssa_emit_context* ctx, uint64_t ftype, uint64_t Rn, uint64_t Rd,
void frintp_scalar_jit(ssa_emit_context* ctx, uint64_t ftype, uint64_t Rn, uint64_t Rd);
void frintm_scalar_jit(ssa_emit_context* ctx, uint64_t ftype, uint64_t Rn, uint64_t Rd);
void fcvtp_scalar_integer_jit(ssa_emit_context* ctx, uint64_t sf, uint64_t ftype, uint64_t U, uint64_t Rn, uint64_t Rd);
void faddp_scalar_jit(ssa_emit_context* ctx, uint64_t sz, uint64_t Rn, uint64_t Rd);
ir_operand _x_jit(ssa_emit_context* ctx, uint64_t reg_id);//THIS FUNCTION IS USER DEFINED
void _x_jit(ssa_emit_context* ctx, uint64_t reg_id, ir_operand value);//THIS FUNCTION IS USER DEFINED
ir_operand _sys_jit(ssa_emit_context* ctx, uint64_t reg_id);//THIS FUNCTION IS USER DEFINED
@@ -489,6 +544,8 @@ void _branch_conditional_jit(ssa_emit_context* ctx, uint64_t yes, uint64_t no, i
ir_operand get_vector_context_jit(ssa_emit_context* ctx);//THIS FUNCTION IS USER DEFINED
void store_context_jit(ssa_emit_context* ctx);//THIS FUNCTION IS USER DEFINED
void load_context_jit(ssa_emit_context* ctx);//THIS FUNCTION IS USER DEFINED
uint64_t use_fast_float_jit(ssa_emit_context* ctx);//THIS FUNCTION IS USER DEFINED
uint64_t use_x86_sse_jit(ssa_emit_context* ctx);//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
+128 -1
View File
@@ -231,6 +231,16 @@ static meta_number NOT(meta_number source)
return source;
}
enum ReduceOp
{
ReduceOp_FMINNUM,
ReduceOp_FMAXNUM,
ReduceOp_FMIN,
ReduceOp_FMAX,
ReduceOp_FADD,
ReduceOp_ADD
};
enum FPType
{
FPType_Zero,
@@ -1733,7 +1743,7 @@ static bits(N) FPRoundInt(bits(N) op, FPCR_Type fpcr, FPRounding rounding, boole
// When alternative floating-point support is TRUE, do not generate
// Input Denormal floating-point exceptions.
auto altfp = IsFeatureImplemented(FEAT_AFP) && !UsingAArch32() && fpcr.AH() == '1';
auto altfp = IsFeatureImplemented(FEAT_AFP) && !UsingAArch32() && fpcr.AH() == 1;
auto fpexc = !altfp;
// Unpack using FPCR to determine if subnormals are flushed-to-zero.
@@ -1992,6 +2002,46 @@ static bits(N) FPRSqrtEstimate(bits(N) operand, FPCR_Type fpcr_in)
return result;
}
static bits(N) FPRecipEstimate(bits(N) operand, FPCR_Type fpcr_in)
{
int N = operand.size;
assert_in(N, {16,32,64});
FPCR_Type fpcr = fpcr_in;
bits(N) result;
boolean overflow_to_inf;
// When using alternative floating-point behavior, do not generate
// floating-point exceptions, flush denormal input and output to zero,
// and use RNE rounding mode.
boolean altfp = IsFeatureImplemented(FEAT_AFP) && !UsingAArch32() && fpcr.AH() == 1;
boolean fpexc = !altfp;
//if altfp then fpcr.<FIZ,FZ> = 11;
//if altfp then fpcr.RMode = 00;
auto [fptype,sign,value] = FPUnpack(operand, fpcr, fpexc);
FPRounding rounding = FPRoundingMode(fpcr);
if (fptype == FPType_SNaN || fptype == FPType_QNaN)
{
result = FPProcessNaN(fptype, operand, fpcr, fpexc);
}
else if (fptype == FPType_Infinity)
{
result = FPZero(sign, N);
}
else if (fptype == FPType_Zero)
{
result = FPInfinity(sign, N);
if (fpexc) FPProcessException(FPExc_DivideByZero, fpcr);
}
else
{
result = FPRound(1.0 / value,fpcr, N);
}
return result;
}
static bits(N) FPOnePointFive(bit sign, integer N)
{
assert_in(N,{16,32,64});
@@ -2004,6 +2054,73 @@ static bits(N) FPOnePointFive(bit sign, integer N)
return result;
}
static bits(N) FPTwo(bit sign, integer N)
{
assert_in(N,{16,32,64});
integer E = (N == 16 ? 5 : N == 32 ? 8 : 11);
integer F = N - (E + 1);
auto exp = meta_number(1,1) | Zeros(E-1);
auto frac = Zeros(F);
auto result = sign | exp | frac;
return result;
}
static bits(N) FPRecipStepFused(bits(N) op1_in, bits(N) op2, FPCR_Type fpcr_in)
{
int N = op1_in.size;
assert_in(N , {16, 32, 64});
FPCR_Type fpcr = fpcr_in;
bits(N) op1 = op1_in;
//bits(N) result;
//boolean done;
op1 = FPNeg(op1, fpcr);
boolean altfp = IsFeatureImplemented(FEAT_AFP) && fpcr.AH() == 1;
boolean fpexc = !altfp; // Generate no floating-point exceptions
//if altfp then fpcr.<FIZ,FZ> = 11; // Flush denormal input and output to zero
//if altfp then fpcr.RMode = 00; // Use RNE rounding mode
auto [type1,sign1,value1] = FPUnpack(op1, fpcr, fpexc);
auto [type2,sign2,value2] = FPUnpack(op2, fpcr, fpexc);
auto [done,result] = FPProcessNaNs(type1, type2, op1, op2, fpcr, fpexc);
FPRounding rounding = FPRoundingMode(fpcr);
if (!done)
{
auto inf1 = (type1 == FPType_Infinity);
auto inf2 = (type2 == FPType_Infinity);
auto zero1 = (type1 == FPType_Zero);
auto zero2 = (type2 == FPType_Zero);
if ((inf1 && zero2) || (zero1 && inf2))
{
result = FPTwo(0, N);
}
else if (inf1 || inf2)
{
result = FPInfinity(sign1 ^ sign2, N);
}
else
{
// Fully fused multiply-add
auto result_value = 2.0 + (value1 * value2);
if (result_value == 0.0)
{
// Sign of exact zero result depends on rounding mode
auto sign = rounding == FPRounding_NEGINF ? 1 : 0;
result = FPZero(sign, N);
}
else
{
result = FPRound(result_value, fpcr, rounding, fpexc, N);
}
}
}
return result;
}
static bits(N) FPRSqrtStepFused(bits(N) op1_in, bits(N) op2, FPCR_Type fpcr_in)
{
int N = op1_in.size;
@@ -2089,6 +2206,11 @@ static uint64_t FPRSqrtEstimate_I(uint64_t op, uint64_t fpcr, uint64_t N)
return FPRSqrtEstimate({op, N}, {fpcr});
}
static uint64_t FPRecipEstimate_I(uint64_t op, uint64_t fpcr, uint64_t N)
{
return FPRecipEstimate({op, N}, {fpcr});
}
static uint64_t FPNeg_I(uint64_t op, uint64_t fpcr, uint64_t N)
{
return FPNeg({op, N}, {fpcr});
@@ -2134,6 +2256,11 @@ static uint64_t FPRSqrtStepFused_I(uint64_t op1, uint64_t op2, uint64_t fpcr, ui
return FPRSqrtStepFused({op1, N}, {op2, N}, {fpcr});
}
static uint64_t FPRecipStepFused_I(uint64_t op1, uint64_t op2, uint64_t fpcr, uint64_t N)
{
return FPRecipStepFused({op1, N}, {op2, N}, {fpcr});
}
static uint64_t FPMul_I(uint64_t op1, uint64_t op2, uint64_t fpcr, uint64_t N)
{
return FPMul({op1, N}, {op2, N}, {fpcr});
+17
View File
@@ -38,6 +38,17 @@ enum ir_instructions : uint64_t
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,
@@ -52,6 +63,7 @@ enum ir_instructions : uint64_t
ir_logical_not,
ir_convert_to_float_signed,
ir_convert_to_float_unsigned,
ir_floating_point_square_root,
ir_unary_end,
@@ -123,6 +135,11 @@ enum ir_instructions : uint64_t
x86_subsd,
x86_subss,
x86_sqrtss,
x86_sqrtsd,
x86_sqrtps,
x86_sqrtpd,
//Emulator Helpers
ir_guest_store_context,
ir_guest_load_context,