475 std::vector<uint8_t> result{};
477 const auto emit_imm8 = [&](
int in_value) -> size_t
479 auto pos = result.size();
481 result.push_back(in_value & 0xFF);
486 const auto emit_imm16 = [&](
int in_value) -> size_t
488 auto pos = emit_imm8(in_value);
490 result.push_back((in_value >> 8) & 0xFF);
495 const auto emit_imm32 = [&](
int in_value) -> size_t
497 auto pos = emit_imm16(in_value);
499 result.push_back((in_value >> 16) & 0xFF);
500 result.push_back((in_value >> 24) & 0xFF);
505 const auto emit_push = [&](
user_register in_register, std::optional<
int> in_offset = {})
509 if (in_offset.has_value())
511 const auto offset = in_offset.value();
514 result.push_back(0xFF);
516 if (!offset && !emit_ebp_no_offset)
519 result.push_back(uint8_t(0x30 | register_id));
521 else if (offset <= 0x7F || emit_ebp_no_offset)
524 result.push_back(uint8_t(0x70 | register_id));
529 result.push_back(uint8_t(0xB0 | register_id));
533 result.push_back(0x24);
535 if (!offset && !emit_ebp_no_offset)
538 if ((offset > 0 && offset <= 0x7F) || emit_ebp_no_offset)
542 else if (offset > 0x7F)
551 result.push_back(uint8_t(0x50 | register_id));
560 const auto emit_add_subtract = [&](
user_register in_register,
int in_value)
566 const auto is_add = in_value > 0;
567 const auto value_abs = std::abs(in_value);
577 result.push_back(uint8_t(opcode | register_id));
586 if (value_abs > 0 && value_abs <= 0x7F)
589 result.push_back(0x83);
590 result.push_back(uint8_t(0xC0 | modifier | register_id));
591 emit_imm8(value_abs);
593 else if (value_abs > 0x7F)
598 result.push_back(uint8_t(0x05 | modifier));
602 result.push_back(0x81);
603 result.push_back(uint8_t(0xC0 | modifier | register_id));
606 emit_imm32(value_abs);
611 const auto emit_load_store_sse = [&](
user_register in_dst,
user_register in_src,
int in_offset = 0,
int in_float_size =
sizeof(
float),
bool in_store =
false)
616 const auto ptr_register = in_store ? in_dst : in_src;
617 const auto ptr_register_id = in_store ? dst_register_id : src_register_id;
619 const auto data_register = in_store ? in_src : in_dst;
620 const auto data_register_id = in_store ? src_register_id : dst_register_id;
628 if (in_float_size ==
sizeof(
double))
631 result.push_back(opcode);
632 result.push_back(0x0F);
633 result.push_back(in_store ? 0x11 : 0x10);
637 if ((in_offset > 0 && in_offset <= 0x7F) || emit_ebp_no_offset)
641 else if (in_offset > 0x7F)
648 result.push_back(uint8_t(0x04 | modifier | (data_register_id << 3)));
649 result.push_back(0x24);
653 result.push_back(uint8_t(modifier | (ptr_register_id << 3) | data_register_id));
656 if ((in_offset > 0 && in_offset <= 0x7F) || emit_ebp_no_offset)
660 emit_imm8(in_offset);
662 else if (in_offset > 0x7F)
666 emit_imm32(in_offset);
670 const auto emit_exchange_register_fpu = [&](
user_register in_register)
676 result.push_back(0xD9);
680 const auto emit_load_store_fpu = [&](
user_register in_register,
int in_offset = 0,
int in_float_size =
sizeof(
float),
bool in_store =
false)
694 if (in_float_size ==
sizeof(
double))
697 result.push_back(opcode);
701 if ((in_offset > 0 && in_offset <= 0x7F) || emit_ebp_no_offset)
705 else if (in_offset > 0x7F)
717 result.push_back(uint8_t(modifier | registerId));
720 result.push_back(0x24);
722 if ((in_offset > 0 && in_offset <= 0x7F) || emit_ebp_no_offset)
725 emit_imm8(in_offset);
727 else if (in_offset > 0x7F)
730 emit_imm32(in_offset);
738 result.push_back(0xDD);
739 result.push_back(uint8_t(0xD8 | registerId));
749 const auto ptr_register = in_store ? in_dst : in_src;
750 const auto ptr_register_id = in_store ? dst_register_id : src_register_id;
752 const auto data_register = in_store ? in_src : in_dst;
753 const auto data_register_id = in_store ? src_register_id : dst_register_id;
764 result.push_back(opcode);
768 if ((in_offset > 0 && in_offset <= 0x7F) || emit_ebp_no_offset)
772 else if (in_offset > 0x7F)
779 result.push_back(uint8_t(0x04 | modifier | (data_register_id << 3)));
780 result.push_back(0x24);
784 result.push_back(uint8_t(modifier | (ptr_register_id << 3) | data_register_id));
787 if ((in_offset > 0 && in_offset <= 0x7F) || emit_ebp_no_offset)
791 emit_imm8(in_offset);
793 else if (in_offset > 0x7F)
797 emit_imm32(in_offset);
808 if (dst_register_family == src_register_family)
810 if (in_dst == in_src)
814 emit_exchange_register_fpu(in_src);
817 emit_load_store_fpu(in_dst);
820 emit_exchange_register_fpu(in_src);
840 emit_exchange_register_fpu(in_dst);
847 emit_exchange_register_fpu(in_dst);
860 emit_exchange_register_fpu(in_src);
867 emit_exchange_register_fpu(in_src);
898 if (in_float_size ==
sizeof(
double))
901 result.push_back(opcode);
902 result.push_back(0x0F);
903 result.push_back(0x10);
904 result.push_back(uint8_t(0xC0 | (src_register_id << 3) | dst_register_id));
909 auto modifier = 0x6E;
915 result.push_back(0x66);
916 result.push_back(0x0F);
917 result.push_back(modifier);
918 result.push_back(uint8_t(0xC0 | (src_register_id << 3) | dst_register_id));
922 emit_move_register_fpu(in_dst, in_src, in_float_size);
931 if (dst_register_family == src_register_family)
933 switch (dst_register_family)
937 result.push_back(0x89);
942 emit_move_register_fpu(in_dst, in_src, in_float_size);
946 emit_move_register_sse(in_dst, in_src, in_float_size);
952 emit_move_register_sse(in_dst, in_src, in_float_size);
956 const auto emit_branch = [&](
bool in_call,
bool in_far) -> size_t
961 result.push_back(0xFF);
962 result.push_back(in_call ? 0x15 : 0x25);
967 result.push_back(in_call ? 0xE8 : 0xE9);
970 return emit_imm32(0);
973 const auto emit_branch_address = [&](
void* in_trampoline, ptrdiff_t in_branch_offset,
void* in_target,
bool in_absolute)
975 const auto offset = uintptr_t(in_trampoline) + in_branch_offset;
979 *
reinterpret_cast<uint32_t*>(offset) = uint32_t(in_target);
983 *
reinterpret_cast<uint32_t*>(offset) = uint32_t(uintptr_t(in_target) - offset -
sizeof(uint32_t));
987 const auto emit_return = [&](size_t in_size = 0)
995 result.push_back(opcode);
1001 emit_imm16(in_size);
1004 const auto register_count = in_info.get_register_count();
1005 const auto stack_param_count = in_info.get_stack_param_count();
1006 const auto param_count = in_info.get_param_count();
1008 auto stack_offset = in_to_original
1010 : stack_param_count * 4;
1015 for (size_t i = 0; i < register_count; i++)
1019 if (!is_protected_register(current_register))
1022 emit_push(current_register);
1028 for (
auto i = param_count; i-- > 0;)
1047 emit_push(current_register);
1055 auto branch_offset = emit_branch(
true, in_to_original);
1064 for (
auto i = register_count; i-- > 0;)
1068 if (!is_protected_register(current_register))
1071 emit_pop(current_register);
1080 if ((in_info.is_return_type<
float>() || in_info.is_return_type<
double>()))
1114 for (size_t i = 0; i < param_count; i++)
1121 if (current_register == return_register)
1127 emit_pop(current_register);
1130 if (stack_param_count > 0)
1132 stack_offset = stack_param_count * 4;
1146 const auto size = result.size();
1148 auto trampoline = _aligned_malloc(size,
sizeof(
void*));
1150 memcpy_s(trampoline, size, result.data(), size);
1152 emit_branch_address(trampoline, branch_offset, in_address, in_to_original);