mirror of
https://github.com/FEX-Emu/FEX.git
synced 2026-10-06 13:00:15 +02:00
Merge pull request #4781 from Sonicadvance1/implement_call_ret_far
OpcodeDispatcher: Implement support for CALLF/RETF
This commit is contained in:
12 files changed
+231
-2
No files matched your search
@@ -959,6 +959,60 @@ void OpDispatchBuilder::JUMPFARIndirectOp(OpcodeArgs) {
|
||||
ExitFunction(RIPOffset);
|
||||
}
|
||||
|
||||
void OpDispatchBuilder::CALLFARIndirectOp(OpcodeArgs) {
|
||||
const auto SrcSize = Op->Flags & FEXCore::X86Tables::DecodeFlags::FLAG_REX_WIDENING ? OpSize::i64Bit : OpSize::i32Bit;
|
||||
|
||||
// Calculate flags early.
|
||||
CalculateDeferredFlags();
|
||||
|
||||
BlockSetRIP = true;
|
||||
|
||||
Ref Src = MakeSegmentAddress(Op, Op->Dest);
|
||||
AddressMode SrcCS = {.Base = Src, .Offset = 4, .AddrSize = OpSize::i64Bit};
|
||||
auto RIPOffset = _LoadMemAutoTSO(GPRClass, OpSize::i32Bit, Src, OpSize::i8Bit);
|
||||
auto NewSegmentCS = _LoadMemAutoTSO(GPRClass, OpSize::i16Bit, SrcCS, OpSize::i8Bit);
|
||||
auto CurrentCS = _LoadContext(OpSize::i16Bit, GPRClass, offsetof(FEXCore::Core::CPUState, cs_idx));
|
||||
|
||||
auto NewRIP = GetRelocatedPC(Op);
|
||||
|
||||
// Push the current CS
|
||||
Push(SrcSize, CurrentCS);
|
||||
|
||||
// Push the return address.
|
||||
Push(SrcSize, NewRIP);
|
||||
|
||||
// Set up the new CSSegment.
|
||||
_StoreContext(OpSize::i16Bit, GPRClass, NewSegmentCS, offsetof(FEXCore::Core::CPUState, cs_idx));
|
||||
UpdatePrefixFromSegment(NewSegmentCS, FEXCore::X86Tables::DecodeFlags::FLAG_CS_PREFIX);
|
||||
|
||||
// Store the new RIP
|
||||
ExitFunction(RIPOffset);
|
||||
}
|
||||
|
||||
void OpDispatchBuilder::RETFARIndirectOp(OpcodeArgs) {
|
||||
const auto GPRSize = GetGPROpSize();
|
||||
const auto SrcSize = Op->Flags & FEXCore::X86Tables::DecodeFlags::FLAG_REX_WIDENING ? OpSize::i64Bit : OpSize::i32Bit;
|
||||
|
||||
Ref SP = _RMWHandle(LoadGPRRegister(X86State::REG_RSP));
|
||||
Ref NewRIP = Pop(SrcSize, SP);
|
||||
Ref NewSegmentCS = Pop(SrcSize, SP);
|
||||
|
||||
// Optional SP offset.
|
||||
if (Op->Src[0].IsLiteral()) {
|
||||
SP = Add(GPRSize, SP, Op->Src[0].Literal());
|
||||
}
|
||||
|
||||
// Store the new stack pointer
|
||||
StoreGPRRegister(X86State::REG_RSP, SP);
|
||||
|
||||
_StoreContext(OpSize::i16Bit, GPRClass, NewSegmentCS, offsetof(FEXCore::Core::CPUState, cs_idx));
|
||||
UpdatePrefixFromSegment(NewSegmentCS, FEXCore::X86Tables::DecodeFlags::FLAG_CS_PREFIX);
|
||||
|
||||
// Store the new RIP
|
||||
ExitFunction(NewRIP);
|
||||
BlockSetRIP = true;
|
||||
}
|
||||
|
||||
void OpDispatchBuilder::TESTOp(OpcodeArgs, uint32_t SrcIndex) {
|
||||
// TEST is an instruction that does an AND between the sources
|
||||
// Result isn't stored in result, only writes to flags
|
||||
|
||||
@@ -349,6 +349,8 @@ public:
|
||||
void JUMPOp(OpcodeArgs);
|
||||
void JUMPAbsoluteOp(OpcodeArgs);
|
||||
void JUMPFARIndirectOp(OpcodeArgs);
|
||||
void CALLFARIndirectOp(OpcodeArgs);
|
||||
void RETFARIndirectOp(OpcodeArgs);
|
||||
void TESTOp(OpcodeArgs, uint32_t SrcIndex);
|
||||
void MOVSXDOp(OpcodeArgs);
|
||||
void MOVSXOp(OpcodeArgs);
|
||||
|
||||
@@ -57,6 +57,7 @@ constexpr inline DispatchTableEntry OpDispatch_BaseOpTable[] = {
|
||||
{0xC2, 2, &OpDispatchBuilder::RETOp},
|
||||
{0xC8, 1, &OpDispatchBuilder::EnterOp},
|
||||
{0xC9, 1, &OpDispatchBuilder::LEAVEOp},
|
||||
{0xCA, 2, &OpDispatchBuilder::RETFARIndirectOp},
|
||||
{0xCC, 2, &OpDispatchBuilder::INTOp},
|
||||
{0xCF, 1, &OpDispatchBuilder::IRETOp},
|
||||
{0xD7, 2, &OpDispatchBuilder::XLATOp},
|
||||
|
||||
@@ -117,6 +117,7 @@ constexpr DispatchTableEntry OpDispatch_PrimaryGroupTables[] = {
|
||||
{OPD(FEXCore::X86Tables::TYPE_GROUP_5, OpToIndex(0xFF), 0), 1, &OpDispatchBuilder::INCOp}, // INC
|
||||
{OPD(FEXCore::X86Tables::TYPE_GROUP_5, OpToIndex(0xFF), 1), 1, &OpDispatchBuilder::DECOp}, // DEC
|
||||
{OPD(FEXCore::X86Tables::TYPE_GROUP_5, OpToIndex(0xFF), 2), 1, &OpDispatchBuilder::CALLAbsoluteOp},
|
||||
{OPD(FEXCore::X86Tables::TYPE_GROUP_5, OpToIndex(0xFF), 3), 1, &OpDispatchBuilder::CALLFARIndirectOp},
|
||||
{OPD(FEXCore::X86Tables::TYPE_GROUP_5, OpToIndex(0xFF), 4), 1, &OpDispatchBuilder::JUMPAbsoluteOp},
|
||||
{OPD(FEXCore::X86Tables::TYPE_GROUP_5, OpToIndex(0xFF), 5), 1, &OpDispatchBuilder::JUMPFARIndirectOp},
|
||||
{OPD(FEXCore::X86Tables::TYPE_GROUP_5, OpToIndex(0xFF), 6), 1, &OpDispatchBuilder::PUSHOp},
|
||||
|
||||
@@ -171,7 +171,8 @@ std::array<X86InstInfo, MAX_PRIMARY_TABLE_SIZE> BaseOps = []() consteval {
|
||||
{0xC3, 1, X86InstInfo{"RET", TYPE_INST, GenFlagsSameSize(SIZE_64BITDEF) | FLAGS_SETS_RIP | FLAGS_BLOCK_END , 0, nullptr}},
|
||||
{0xC8, 1, X86InstInfo{"ENTER", TYPE_INST, GenFlagsSameSize(SIZE_64BITDEF) | FLAGS_DEBUG_MEM_ACCESS , 3, nullptr}},
|
||||
{0xC9, 1, X86InstInfo{"LEAVE", TYPE_INST, GenFlagsSameSize(SIZE_64BITDEF) | FLAGS_DEBUG_MEM_ACCESS , 0, nullptr}},
|
||||
{0xCA, 2, X86InstInfo{"RETF", TYPE_PRIV, GenFlagsSameSize(SIZE_64BITDEF) | FLAGS_SETS_RIP | FLAGS_BLOCK_END, 0, nullptr}},
|
||||
{0xCA, 1, X86InstInfo{"RETF", TYPE_INST, GenFlagsSameSize(SIZE_64BITDEF) | FLAGS_SETS_RIP | FLAGS_BLOCK_END, 2, nullptr}},
|
||||
{0xCB, 1, X86InstInfo{"RETF", TYPE_INST, GenFlagsSameSize(SIZE_64BITDEF) | FLAGS_SETS_RIP | FLAGS_BLOCK_END, 0, nullptr}},
|
||||
{0xCC, 1, X86InstInfo{"INT3", TYPE_INST, FLAGS_BLOCK_END, 0, nullptr}},
|
||||
{0xCD, 1, X86InstInfo{"INT", TYPE_INST, DEFAULT_SYSCALL_FLAGS, 1, nullptr}},
|
||||
{0xCF, 1, X86InstInfo{"IRET", TYPE_INST, FLAGS_SETS_RIP | FLAGS_BLOCK_END, 0, nullptr}},
|
||||
|
||||
@@ -129,7 +129,7 @@ std::array<X86InstInfo, MAX_INST_GROUP_TABLE_SIZE> PrimaryInstGroupOps = []() co
|
||||
{OPD(TYPE_GROUP_5, OpToIndex(0xFF), 0), 1, X86InstInfo{"INC", TYPE_INST, FLAGS_MODRM | FLAGS_SF_MOD_DST, 0, nullptr}},
|
||||
{OPD(TYPE_GROUP_5, OpToIndex(0xFF), 1), 1, X86InstInfo{"DEC", TYPE_INST, FLAGS_MODRM | FLAGS_SF_MOD_DST, 0, nullptr}},
|
||||
{OPD(TYPE_GROUP_5, OpToIndex(0xFF), 2), 1, X86InstInfo{"CALL", TYPE_INST, GenFlagsSameSize(SIZE_64BITDEF) | FLAGS_SETS_RIP | FLAGS_MODRM | FLAGS_BLOCK_END | FLAGS_CALL , 0, nullptr}},
|
||||
{OPD(TYPE_GROUP_5, OpToIndex(0xFF), 3), 1, X86InstInfo{"CALLF", TYPE_INST, FLAGS_SETS_RIP | FLAGS_MODRM | FLAGS_BLOCK_END, 0, nullptr}},
|
||||
{OPD(TYPE_GROUP_5, OpToIndex(0xFF), 3), 1, X86InstInfo{"CALLF", TYPE_INST, FLAGS_SETS_RIP | FLAGS_MODRM | FLAGS_SF_MOD_DST | FLAGS_SF_MOD_MEM_ONLY | FLAGS_BLOCK_END, 0, nullptr}},
|
||||
{OPD(TYPE_GROUP_5, OpToIndex(0xFF), 4), 1, X86InstInfo{"JMP", TYPE_INST, GenFlagsSameSize(SIZE_64BITDEF) | FLAGS_SETS_RIP | FLAGS_MODRM | FLAGS_BLOCK_END , 0, nullptr}},
|
||||
{OPD(TYPE_GROUP_5, OpToIndex(0xFF), 5), 1, X86InstInfo{"JMPF", TYPE_INST, FLAGS_SETS_RIP | FLAGS_MODRM | FLAGS_SF_MOD_DST | FLAGS_SF_MOD_MEM_ONLY | FLAGS_BLOCK_END, 0, nullptr}},
|
||||
{OPD(TYPE_GROUP_5, OpToIndex(0xFF), 6), 1, X86InstInfo{"PUSH", TYPE_INST, GenFlagsSameSize(SIZE_64BITDEF) | FLAGS_DEBUG_MEM_ACCESS | FLAGS_MODRM, 0, nullptr}},
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
%ifdef CONFIG
|
||||
{
|
||||
"RegData": {
|
||||
"RAX": "1",
|
||||
"RBX": "0xe0000fe8",
|
||||
"RSP": "0xe0000ff0"
|
||||
}
|
||||
}
|
||||
%endif
|
||||
|
||||
mov rsp, 0xe000_1000
|
||||
mov ax, cs
|
||||
lea edi, [rel .success]
|
||||
|
||||
sub rsp, 16
|
||||
mov [rsp], edi
|
||||
mov [rsp+4], cs
|
||||
|
||||
mov rax, 0
|
||||
call far dword [esp]
|
||||
|
||||
hlt
|
||||
|
||||
.success:
|
||||
mov rax, 1
|
||||
mov rbx, rsp
|
||||
o32 retf
|
||||
@@ -0,0 +1,27 @@
|
||||
%ifdef CONFIG
|
||||
{
|
||||
"RegData": {
|
||||
"RAX": "1",
|
||||
"RBX": "0xe0000fe8",
|
||||
"RSP": "0xe0002224"
|
||||
}
|
||||
}
|
||||
%endif
|
||||
|
||||
mov rsp, 0xe000_1000
|
||||
mov ax, cs
|
||||
lea edi, [rel .success]
|
||||
|
||||
sub rsp, 16
|
||||
mov [rsp], edi
|
||||
mov [rsp+4], cs
|
||||
|
||||
mov rax, 0
|
||||
call far dword [esp]
|
||||
|
||||
hlt
|
||||
|
||||
.success:
|
||||
mov rax, 1
|
||||
mov rbx, rsp
|
||||
o32 retf 0x1234
|
||||
@@ -0,0 +1,27 @@
|
||||
%ifdef CONFIG
|
||||
{
|
||||
"RegData": {
|
||||
"RAX": "1",
|
||||
"RBX": "0xe0000fe0",
|
||||
"RSP": "0xe0000ff0"
|
||||
}
|
||||
}
|
||||
%endif
|
||||
|
||||
mov rsp, 0xe000_1000
|
||||
mov ax, cs
|
||||
lea edi, [rel .success]
|
||||
|
||||
sub rsp, 16
|
||||
mov [rsp], edi
|
||||
mov [rsp+4], cs
|
||||
|
||||
mov rax, 0
|
||||
o64 call far [rsp]
|
||||
|
||||
hlt
|
||||
|
||||
.success:
|
||||
mov rax, 1
|
||||
mov rbx, rsp
|
||||
o64 retf
|
||||
@@ -0,0 +1,27 @@
|
||||
%ifdef CONFIG
|
||||
{
|
||||
"RegData": {
|
||||
"RAX": "1",
|
||||
"RBX": "0xe0000fe0",
|
||||
"RSP": "0xe00090f0"
|
||||
}
|
||||
}
|
||||
%endif
|
||||
|
||||
mov rsp, 0xe000_1000
|
||||
mov ax, cs
|
||||
lea edi, [rel .success]
|
||||
|
||||
sub rsp, 16
|
||||
mov [rsp], edi
|
||||
mov [rsp+4], cs
|
||||
|
||||
mov rax, 0
|
||||
o64 call far [rsp]
|
||||
|
||||
hlt
|
||||
|
||||
.success:
|
||||
mov rax, 1
|
||||
mov rbx, rsp
|
||||
o64 retf 0x8100
|
||||
@@ -4473,6 +4473,45 @@
|
||||
"bfxil x4, x20, #0, #8"
|
||||
]
|
||||
},
|
||||
"retf 0x1234": {
|
||||
"ExpectedInstructionCount": 15,
|
||||
"Comment": "0xca",
|
||||
"ExpectedArm64ASM": [
|
||||
"mov x20, x8",
|
||||
"ldp w21, w22, [x20], #8",
|
||||
"mov w23, #0x1234",
|
||||
"add x8, x20, x23",
|
||||
"strh w22, [x28, #930]",
|
||||
"ubfx w20, w22, #2, #1",
|
||||
"and w22, w22, #0xfff8",
|
||||
"add x0, x28, x20, lsl #3",
|
||||
"ldr x20, [x0, #1168]",
|
||||
"ldr x20, [x20, w22, uxtw]",
|
||||
"lsr x22, x20, #32",
|
||||
"and w23, w22, #0xff000000",
|
||||
"orr w20, w23, w20, lsr #16",
|
||||
"bfi w20, w22, #16, #8",
|
||||
"str w20, [x28, #948]"
|
||||
]
|
||||
},
|
||||
"retf": {
|
||||
"ExpectedInstructionCount": 12,
|
||||
"Comment": "0xcb",
|
||||
"ExpectedArm64ASM": [
|
||||
"ldp w20, w21, [x8], #8",
|
||||
"strh w21, [x28, #930]",
|
||||
"ubfx w22, w21, #2, #1",
|
||||
"and w21, w21, #0xfff8",
|
||||
"add x0, x28, x22, lsl #3",
|
||||
"ldr x22, [x0, #1168]",
|
||||
"ldr x21, [x22, w21, uxtw]",
|
||||
"lsr x22, x21, #32",
|
||||
"and w23, w22, #0xff000000",
|
||||
"orr w21, w23, w21, lsr #16",
|
||||
"bfi w21, w22, #16, #8",
|
||||
"str w21, [x28, #948]"
|
||||
]
|
||||
},
|
||||
"cmc": {
|
||||
"ExpectedInstructionCount": 3,
|
||||
"Comment": "0xf5",
|
||||
|
||||
@@ -2973,6 +2973,29 @@
|
||||
"strh w4, [x8, #-2]!"
|
||||
]
|
||||
},
|
||||
"call far [rsp]": {
|
||||
"ExpectedInstructionCount": 17,
|
||||
"Comment": "GROUP5 0xff /3",
|
||||
"ExpectedArm64ASM": [
|
||||
"ldr w20, [x8]",
|
||||
"ldrh w21, [x8, #4]",
|
||||
"ldrh w22, [x28, #930]",
|
||||
"mov w23, #0x4",
|
||||
"movk w23, #0x1, lsl #16",
|
||||
"stp x23, x22, [x8, #-16]!",
|
||||
"strh w21, [x28, #930]",
|
||||
"ubfx w22, w21, #2, #1",
|
||||
"and w21, w21, #0xfff8",
|
||||
"add x0, x28, x22, lsl #3",
|
||||
"ldr x22, [x0, #1168]",
|
||||
"ldr x21, [x22, w21, uxtw]",
|
||||
"lsr x22, x21, #32",
|
||||
"and w23, w22, #0xff000000",
|
||||
"orr w21, w23, w21, lsr #16",
|
||||
"bfi w21, w22, #16, #8",
|
||||
"str w21, [x28, #948]"
|
||||
]
|
||||
},
|
||||
"push rax": {
|
||||
"ExpectedInstructionCount": 1,
|
||||
"Comment": "GROUP4 0xff /6",
|
||||
|
||||
Reference in new issue
Block a user