413 std::vector<uint8_t> result{};
415 const auto emitImm8 = [&](
int in_value)
417 auto pos = result.size();
419 result.push_back(in_value & 0xFF);
424 const auto emitImm16 = [&](
int in_value)
426 auto pos = emitImm8(in_value);
428 result.push_back((in_value >> 8) & 0xFF);
433 const auto emitImm32 = [&](
int in_value)
435 auto pos = emitImm16(in_value);
437 result.push_back((in_value >> 16) & 0xFF);
438 result.push_back((in_value >> 24) & 0xFF);
443 const auto emitPush = [&](
UserRegister in_register, std::optional<
int> in_offset = {})
447 if (in_offset.has_value())
449 const auto offset = in_offset.value();
452 result.push_back(0xFF);
454 if (!offset && !emitEbpNoOffset)
457 result.push_back(uint8_t(0x30 | registerId));
459 else if (offset <= 0x7F || emitEbpNoOffset)
462 result.push_back(uint8_t(0x70 | registerId));
467 result.push_back(uint8_t(0xB0 | registerId));
471 result.push_back(0x24);
473 if (!offset && !emitEbpNoOffset)
476 if ((offset > 0 && offset <= 0x7F) || emitEbpNoOffset)
480 else if (offset > 0x7F)
489 result.push_back(uint8_t(0x50 | registerId));
498 const auto emitAddSubtract = [&](
UserRegister in_register,
int in_value)
504 const auto isAdd = in_value > 0;
505 const auto valueAbs = std::abs(in_value);
515 result.push_back(uint8_t(opcode | registerId));
524 if (valueAbs > 0 && valueAbs <= 0x7F)
527 result.push_back(0x83);
528 result.push_back(uint8_t(0xC0 | modifier | registerId));
531 else if (valueAbs > 0x7F)
536 result.push_back(uint8_t(0x05 | modifier));
540 result.push_back(0x81);
541 result.push_back(uint8_t(0xC0 | modifier | registerId));
549 const auto emitLoadStoreSSE = [&](
UserRegister in_dst,
UserRegister in_src,
int in_offset = 0,
int in_floatSize =
sizeof(
float),
bool in_isStore =
false)
554 const auto ptrRegister = in_isStore ? in_dst : in_src;
555 const auto ptrRegisterId = in_isStore ? dstRegisterId : srcRegisterId;
557 const auto dataRegister = in_isStore ? in_src : in_dst;
558 const auto dataRegisterId = in_isStore ? srcRegisterId : dstRegisterId;
566 if (in_floatSize ==
sizeof(
double))
569 result.push_back(opcode);
570 result.push_back(0x0F);
571 result.push_back(in_isStore ? 0x11 : 0x10);
575 if ((in_offset > 0 && in_offset <= 0x7F) || emitEbpNoOffset)
579 else if (in_offset > 0x7F)
586 result.push_back(uint8_t(0x04 | modifier | (dataRegisterId << 3)));
587 result.push_back(0x24);
591 result.push_back(uint8_t(modifier | (ptrRegisterId << 3) | dataRegisterId));
594 if ((in_offset > 0 && in_offset <= 0x7F) || emitEbpNoOffset)
600 else if (in_offset > 0x7F)
604 emitImm32(in_offset);
608 const auto emitExchangeRegisterFPU = [&](
UserRegister in_register)
614 result.push_back(0xD9);
618 const auto emitLoadStoreFPU = [&](
UserRegister in_register,
int in_offset = 0,
int in_floatSize =
sizeof(
float),
bool in_isStore =
false)
632 if (in_floatSize ==
sizeof(
double))
635 result.push_back(opcode);
639 if ((in_offset > 0 && in_offset <= 0x7F) || emitEbpNoOffset)
643 else if (in_offset > 0x7F)
655 result.push_back(uint8_t(modifier | registerId));
658 result.push_back(0x24);
660 if ((in_offset > 0 && in_offset <= 0x7F) || emitEbpNoOffset)
665 else if (in_offset > 0x7F)
668 emitImm32(in_offset);
676 result.push_back(0xDD);
677 result.push_back(uint8_t(0xD8 | registerId));
682 const auto emitLoadStore = [&](
UserRegister in_dst,
UserRegister in_src,
int in_offset = 0,
bool in_isStore =
false)
687 const auto ptrRegister = in_isStore ? in_dst : in_src;
688 const auto ptrRegisterId = in_isStore ? dstRegisterId : srcRegisterId;
690 const auto dataRegister = in_isStore ? in_src : in_dst;
691 const auto dataRegisterId = in_isStore ? srcRegisterId : dstRegisterId;
702 result.push_back(opcode);
706 if ((in_offset > 0 && in_offset <= 0x7F) || emitEbpNoOffset)
710 else if (in_offset > 0x7F)
717 result.push_back(uint8_t(0x04 | modifier | (dataRegisterId << 3)));
718 result.push_back(0x24);
722 result.push_back(uint8_t(modifier | (ptrRegisterId << 3) | dataRegisterId));
725 if ((in_offset > 0 && in_offset <= 0x7F) || emitEbpNoOffset)
731 else if (in_offset > 0x7F)
735 emitImm32(in_offset);
748 if (dstRegisterFamily == srcRegisterFamily)
750 if (in_dst == in_src)
754 emitExchangeRegisterFPU(in_src);
757 emitLoadStoreFPU(in_dst);
760 emitExchangeRegisterFPU(in_src);
780 emitExchangeRegisterFPU(in_dst);
787 emitExchangeRegisterFPU(in_dst);
800 emitExchangeRegisterFPU(in_src);
807 emitExchangeRegisterFPU(in_src);
838 if (in_floatSize ==
sizeof(
double))
841 result.push_back(opcode);
842 result.push_back(0x0F);
843 result.push_back(0x10);
844 result.push_back(uint8_t(0xC0 | (srcRegisterId << 3) | dstRegisterId));
849 auto modifier = 0x6E;
855 result.push_back(0x66);
856 result.push_back(0x0F);
857 result.push_back(modifier);
858 result.push_back(uint8_t(0xC0 | (srcRegisterId << 3) | dstRegisterId));
862 emitMoveRegisterFPU(in_dst, in_src, in_floatSize);
871 if (dstRegisterFamily == srcRegisterFamily)
873 switch (dstRegisterFamily)
877 result.push_back(0x89);
882 emitMoveRegisterFPU(in_dst, in_src, in_floatSize);
886 emitMoveRegisterSSE(in_dst, in_src, in_floatSize);
892 emitMoveRegisterSSE(in_dst, in_src, in_floatSize);
896 const auto emitBranch = [&](
bool in_isCall,
bool in_isFar)
901 result.push_back(0xFF);
902 result.push_back(in_isCall ? 0x15 : 0x25);
907 result.push_back(in_isCall ? 0xE8 : 0xE9);
913 const auto emitBranchAddr = [&](
void* in_pStart, size_t in_branchOffset, size_t in_target,
bool in_isAbsolute)
915 const auto offset = size_t(in_pStart) + in_branchOffset;
919 *(uint32_t*)offset = uint32_t(in_target);
923 *(uint32_t*)offset = uint32_t((in_target - offset) -
sizeof(uint32_t));
927 const auto emitReturn = [&](size_t in_size = 0)
935 result.push_back(opcode);
944 const auto registerCount = in_rInfo.GetRegisterCount();
945 const auto stackParamCount = in_rInfo.GetStackParamCount();
946 const auto paramCount = in_rInfo.GetParamCount();
948 auto stackOffset = in_isToOriginal
950 : stackParamCount * 4;
955 for (size_t i = 0; i < registerCount; i++)
962 emitPush(currentRegister);
968 for (
auto i = paramCount; i-- > 0;)
987 emitPush(currentRegister);
995 auto branchOffset = emitBranch(
true, in_isToOriginal);
1004 for (
auto i = registerCount; i-- > 0;)
1011 emitPop(currentRegister);
1024 if (in_isToOriginal)
1036 if (in_isToOriginal)
1047 if (in_isToOriginal)
1054 for (size_t i = 0; i < paramCount; i++)
1061 if (currentRegister == returnRegister)
1067 emitPop(currentRegister);
1070 if (stackParamCount > 0)
1072 stackOffset = stackParamCount * 4;
1086 const auto size = result.size();
1088 auto pTrampoline = _aligned_malloc(size,
sizeof(
void*));
1089 memcpy_s(pTrampoline, size, result.data(), size);
1090 emitBranchAddr(pTrampoline, branchOffset, in_address, in_isToOriginal);
1092 hedgedev::csl::mem::Protect(pTrampoline, size, hedgedev::csl::mem::GetProtectionFlags(hedgedev::csl::mem::PageProtection::RWX));