mirror of
https://github.com/boykopovar/AnyPS5.git
synced 2026-11-04 13:07:32 +00:00
feat(relinker): --to-intel lowers SSE4a sites to same-length jumps into an appended stub section
EXTRQ, INSERTQ, MOVNTSS and MOVNTSD are rewritten at relink time: same-length in-place forms where they exist, otherwise a jmp rel32 into an appended executable section holding a scratch-free SSE body and a jump back, so no code shifts and no RIP-relative or jump-table operand needs adjusting. Decoder fixes for POPCNT and 0F BB (BTC), codegen and elfpatcher tests, README and technical-debt notes. The runtime illegal-instruction trap stays as a fallback. Co-Authored-By: Claude Fable 5.1 <[email protected]> Claude-Session: https://claude.ai/code/session_0177gthrWEBBfBu5xJDXgBfo
This commit is contained in:
1 parent
af3c2024ed
commit
01c4e3edf7
28 files changed
+1515
-77
No files matched your search
@@ -1,6 +1,7 @@
|
||||
#ifndef CODEGEN_CODEGENTYPES_HPP
|
||||
#define CODEGEN_CODEGENTYPES_HPP
|
||||
|
||||
#include <codegen/x86/Amd64OnlySubstitutionTypes.hpp>
|
||||
#include <domain/Types.hpp>
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
@@ -28,9 +29,20 @@ struct RewriteResult {
|
||||
std::vector<AddressAdjustment> Adjustments;
|
||||
};
|
||||
|
||||
struct TrampolineSite {
|
||||
Domain::FileByteOffset Offset;
|
||||
Domain::VirtualAddress Address;
|
||||
std::size_t Length;
|
||||
std::vector<std::uint8_t> OriginalBytes;
|
||||
std::vector<std::uint8_t> Body;
|
||||
std::size_t ReturnBranchOffset;
|
||||
};
|
||||
|
||||
struct ConvertResult {
|
||||
std::vector<std::uint8_t> Bytes;
|
||||
std::size_t ReplacedCount;
|
||||
std::vector<TrampolineSite> Trampolines;
|
||||
std::vector<Amd64OnlySubstitutionReport> Reports;
|
||||
};
|
||||
|
||||
enum class ControlFlowKind : std::uint8_t {
|
||||
|
||||
@@ -17,14 +17,39 @@ struct Entry {
|
||||
inline constexpr std::uint8_t k##name##Bytes[] = {__VA_ARGS__}; \
|
||||
inline constexpr Entry k##name = {#name, k##name##Bytes, sizeof(k##name##Bytes)};
|
||||
|
||||
AMD64_STUB(Monitorx, 0x0F, 0x01, 0xFA)
|
||||
AMD64_STUB(Mwaitx, 0x0F, 0x01, 0xFB)
|
||||
AMD64_STUB(Clzero, 0x0F, 0x01, 0xFC)
|
||||
AMD64_STUB(Rdpru, 0x0F, 0x01, 0xFD)
|
||||
AMD64_STUB(Mcommit, 0xF3, 0x0F, 0x01, 0xFA)
|
||||
AMD64_STUB(JmpRel32, 0xE9, 0x00, 0x00, 0x00, 0x00)
|
||||
AMD64_STUB(LeaRspBelowRedZone, 0x48, 0x8D, 0xA4, 0x24, 0x70, 0xFF, 0xFF, 0xFF)
|
||||
AMD64_STUB(LeaRspRestore, 0x48, 0x8D, 0xA4, 0x24, 0x90, 0x00, 0x00, 0x00)
|
||||
AMD64_STUB(Nop1, 0x90)
|
||||
AMD64_STUB(Nop2, 0x66, 0x90)
|
||||
AMD64_STUB(Nop3, 0x0F, 0x1F, 0x00)
|
||||
AMD64_STUB(Nop4, 0x0F, 0x1F, 0x40, 0x00)
|
||||
AMD64_STUB(Nop5, 0x0F, 0x1F, 0x44, 0x00, 0x00)
|
||||
AMD64_STUB(Nop6, 0x66, 0x0F, 0x1F, 0x44, 0x00, 0x00)
|
||||
AMD64_STUB(Nop7, 0x0F, 0x1F, 0x80, 0x00, 0x00, 0x00, 0x00)
|
||||
|
||||
#undef AMD64_STUB
|
||||
|
||||
inline constexpr Entry kNops[] = {kNop1, kNop2, kNop3, kNop4, kNop5, kNop6, kNop7};
|
||||
|
||||
inline constexpr Entry kMonitorx = {"MONITORX", nullptr, 0};
|
||||
inline constexpr Entry kMwaitx = {"MWAITX", nullptr, 0};
|
||||
inline constexpr Entry kClzero = {"CLZERO", nullptr, 0};
|
||||
inline constexpr Entry kRdpru = {"RDPRU", nullptr, 0};
|
||||
inline constexpr Entry kMcommit = {"MCOMMIT", nullptr, 0};
|
||||
inline constexpr Entry kExtrq = {"EXTRQ", nullptr, 0};
|
||||
inline constexpr Entry kInsertq = {"INSERTQ", nullptr, 0};
|
||||
inline constexpr Entry kExtrqRegisterForm = {"EXTRQ register form", nullptr, 0};
|
||||
inline constexpr Entry kInsertqRegisterForm = {"INSERTQ register form", nullptr, 0};
|
||||
inline constexpr Entry kMovntss = {"MOVNTSS", nullptr, 0};
|
||||
inline constexpr Entry kMovntsd = {"MOVNTSD", nullptr, 0};
|
||||
|
||||
inline constexpr std::uint8_t kMovsStoreOpcode = 0x11;
|
||||
inline constexpr std::uint8_t kPshufbZero = 0x80;
|
||||
inline constexpr std::uint8_t kTrapFill = 0xCC;
|
||||
inline constexpr std::size_t kStubAlignment = 16;
|
||||
inline constexpr std::size_t kRedZoneSpillFrame = 0x90;
|
||||
|
||||
} // namespace Amd64OnlySubstitutionTable
|
||||
} // namespace Codegen
|
||||
|
||||
|
||||
@@ -8,10 +8,19 @@
|
||||
|
||||
namespace Codegen {
|
||||
|
||||
enum class Amd64OnlyLowering : std::uint8_t {
|
||||
InPlace,
|
||||
Trampoline,
|
||||
Unsupported
|
||||
};
|
||||
|
||||
struct Amd64OnlyMatch {
|
||||
std::string InstructionName;
|
||||
std::size_t Length;
|
||||
Amd64OnlyLowering Lowering;
|
||||
std::vector<std::uint8_t> ReplacementBytes;
|
||||
std::vector<std::uint8_t> StubBody;
|
||||
std::size_t ReturnBranchOffset;
|
||||
};
|
||||
|
||||
struct Amd64OnlySubstitutionReport {
|
||||
@@ -19,6 +28,7 @@ struct Amd64OnlySubstitutionReport {
|
||||
Domain::FileByteOffset Offset;
|
||||
std::size_t OriginalLength;
|
||||
std::size_t ReplacementLength;
|
||||
Amd64OnlyLowering Lowering;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ struct DecodedInstruction {
|
||||
const std::uint8_t* Data;
|
||||
std::size_t Length;
|
||||
|
||||
[[nodiscard]] std::size_t OpcodeOffset() const;
|
||||
[[nodiscard]] bool IsShaNi() const;
|
||||
[[nodiscard]] bool IsExtrq() const;
|
||||
[[nodiscard]] bool IsInsertq() const;
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
#ifndef CODEGEN_X86_SSE4ALOWERING_HPP
|
||||
#define CODEGEN_X86_SSE4ALOWERING_HPP
|
||||
|
||||
#include <codegen/x86/Sse4aOperands.hpp>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <optional>
|
||||
#include <vector>
|
||||
|
||||
namespace Codegen {
|
||||
|
||||
struct LoweredBody {
|
||||
std::vector<std::uint8_t> Bytes;
|
||||
std::size_t ReturnBranchOffset;
|
||||
};
|
||||
|
||||
class Sse4aLowering {
|
||||
public:
|
||||
[[nodiscard]] std::optional<std::vector<std::uint8_t>> LowerInPlace(const Sse4aOperands& operands, std::size_t originalLength) const;
|
||||
[[nodiscard]] LoweredBody LowerOutOfLine(const Sse4aOperands& operands) const;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,22 @@
|
||||
#ifndef CODEGEN_X86_SSE4AOPERANDS_HPP
|
||||
#define CODEGEN_X86_SSE4AOPERANDS_HPP
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
|
||||
namespace Codegen {
|
||||
|
||||
struct Sse4aOperands {
|
||||
bool Insertq;
|
||||
bool RegisterForm;
|
||||
std::uint8_t Destination;
|
||||
std::uint8_t Source;
|
||||
std::uint8_t Length;
|
||||
std::uint8_t Index;
|
||||
};
|
||||
|
||||
[[nodiscard]] Sse4aOperands DecodeSse4a(const std::uint8_t* data, std::size_t length);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -106,6 +106,10 @@ inline constexpr std::uint8_t OneByteLoop = 0xE0;
|
||||
inline constexpr std::uint8_t OneByteLoopMax = 0xE2;
|
||||
inline constexpr std::uint8_t OneByteInOutImm8Min = 0xE4;
|
||||
inline constexpr std::uint8_t OneByteInOutImm8Max = 0xE7;
|
||||
inline constexpr std::uint8_t OneByteInt = 0xCD;
|
||||
inline constexpr std::uint8_t OneByteRetImm16 = 0xC2;
|
||||
inline constexpr std::uint8_t OneByteRetFarImm16 = 0xCA;
|
||||
inline constexpr std::uint8_t OneByteEnter = 0xC8;
|
||||
|
||||
inline constexpr std::uint8_t TwoByteJccRel32Min = 0x80;
|
||||
inline constexpr std::uint8_t TwoByteJccRel32Max = 0x8F;
|
||||
@@ -158,6 +162,19 @@ inline constexpr std::uint8_t TwoByteShufpdImm8 = 0xC6;
|
||||
inline constexpr std::uint8_t TwoByteGrp9 = 0xC7;
|
||||
inline constexpr std::uint8_t TwoByteExtrqInsertqImm8Imm8 = 0x78;
|
||||
inline constexpr std::uint8_t TwoByteExtrqInsertqModRm = 0x79;
|
||||
inline constexpr std::uint8_t TwoByteMovnts = 0x2B;
|
||||
inline constexpr std::uint8_t TwoByteGrp6 = 0x00;
|
||||
inline constexpr std::uint8_t TwoByteLar = 0x02;
|
||||
inline constexpr std::uint8_t TwoByteLsl = 0x03;
|
||||
inline constexpr std::uint8_t TwoBytePrefetchw = 0x0D;
|
||||
inline constexpr std::uint8_t TwoByteMovCrDrMin = 0x20;
|
||||
inline constexpr std::uint8_t TwoByteMovCrDrMax = 0x23;
|
||||
inline constexpr std::uint8_t TwoBytePopcnt = 0xB8;
|
||||
inline constexpr std::uint8_t TwoByteUd1 = 0xB9;
|
||||
inline constexpr std::uint8_t TwoByteBtc = 0xBB;
|
||||
inline constexpr std::uint8_t TwoByteXaddRm8 = 0xC0;
|
||||
inline constexpr std::uint8_t TwoByteMovnti = 0xC3;
|
||||
inline constexpr std::uint8_t TwoBytePinsrw = 0xC4;
|
||||
|
||||
inline constexpr std::uint8_t VexNoModRmMin = 0x77;
|
||||
inline constexpr std::uint8_t VexNoModRmMax = 0x77;
|
||||
@@ -171,6 +188,7 @@ inline constexpr std::uint8_t EvexMap0F38 = 0x02;
|
||||
inline constexpr std::size_t ImmSizeNone = 0;
|
||||
inline constexpr std::size_t ImmSize8 = 1;
|
||||
inline constexpr std::size_t ImmSize16 = 2;
|
||||
inline constexpr std::size_t ImmSizeEnter = 3;
|
||||
inline constexpr std::size_t ImmSize32 = 4;
|
||||
inline constexpr std::size_t ImmSize64 = 8;
|
||||
|
||||
|
||||
Reference in new issue
Block a user