Merge pull request #9 from Sonicadvance1/unittests/stos

Adds unit tests for the STOS instruction family
This commit is contained in:
Stefanos Kornilios Mitsis Poiitidis authored and GitHub committed 2020-03-10 15:25:49 +02:00
commit e2e9e1eb41
13 files changed
+483 -46

No files matched your search

+73 -46
View File
@@ -1748,71 +1748,98 @@ void OpDispatchBuilder::DECOp(OpcodeArgs) {
}
void OpDispatchBuilder::STOSOp(OpcodeArgs) {
LogMan::Throw::A(Op->Flags & FEXCore::X86Tables::DecodeFlags::FLAG_REP_PREFIX, "Can't handle REP not existing on STOS\n");
LogMan::Throw::A(!(Op->Flags & FEXCore::X86Tables::DecodeFlags::FLAG_REPNE_PREFIX), "Invalid REPNE on STOS");
auto Size = GetSrcSize(Op);
// Create all our blocks
auto LoopHead = CreateNewCodeBlock();
auto LoopTail = CreateNewCodeBlock();
auto LoopEnd = CreateNewCodeBlock();
// At the time this was written, our RA can't handle accessing nodes across blocks.
// So we need to re-load and re-calculate essential values each iteration of the loop.
bool Repeat = Op->Flags & FEXCore::X86Tables::DecodeFlags::FLAG_REP_PREFIX;
// First thing we need to do is finish this block and jump to the start of the loop.
_Jump(LoopHead);
if (!Repeat) {
OrderedNode *Src = LoadSource(GPRClass, Op, Op->Src[0], Op->Flags, -1);
OrderedNode *Dest = _LoadContext(8, offsetof(FEXCore::Core::CPUState, gregs[FEXCore::X86State::REG_RDI]), GPRClass);
SetCurrentCodeBlock(LoopHead);
{
OrderedNode *Counter = _LoadContext(8, offsetof(FEXCore::Core::CPUState, gregs[FEXCore::X86State::REG_RCX]), GPRClass);
auto ZeroConst = _Constant(0);
// Store to memory where RDI points
_StoreMem(GPRClass, Size, Dest, Src, Size);
// Can we end the block?
auto CanLeaveCond = _Select(FEXCore::IR::COND_EQ,
Counter, ZeroConst,
_Constant(1), ZeroConst);
auto SizeConst = _Constant(Size);
auto NegSizeConst = _Constant(-Size);
_CondJump(CanLeaveCond, LoopEnd, LoopTail);
}
// Calculate direction.
auto DF = GetRFLAG(FEXCore::X86State::RFLAG_DF_LOC);
auto PtrDir = _Select(FEXCore::IR::COND_EQ,
DF, _Constant(0),
SizeConst, NegSizeConst);
SetCurrentCodeBlock(LoopTail);
{
OrderedNode *Src = LoadSource(GPRClass, Op, Op->Src[0], Op->Flags, -1);
OrderedNode *Dest = _LoadContext(8, offsetof(FEXCore::Core::CPUState, gregs[FEXCore::X86State::REG_RDI]), GPRClass);
// Offset the pointer
OrderedNode *TailDest = _LoadContext(8, offsetof(FEXCore::Core::CPUState, gregs[FEXCore::X86State::REG_RDI]), GPRClass);
TailDest = _Add(TailDest, PtrDir);
_StoreContext(GPRClass, 8, offsetof(FEXCore::Core::CPUState, gregs[FEXCore::X86State::REG_RDI]), TailDest);
// Store to memory where RDI points
_StoreMem(GPRClass, Size, Dest, Src, Size);
}
else {
// Create all our blocks
auto LoopHead = CreateNewCodeBlock();
auto LoopTail = CreateNewCodeBlock();
auto LoopEnd = CreateNewCodeBlock();
OrderedNode *TailCounter = _LoadContext(8, offsetof(FEXCore::Core::CPUState, gregs[FEXCore::X86State::REG_RCX]), GPRClass);
OrderedNode *TailDest = _LoadContext(8, offsetof(FEXCore::Core::CPUState, gregs[FEXCore::X86State::REG_RDI]), GPRClass);
// At the time this was written, our RA can't handle accessing nodes across blocks.
// So we need to re-load and re-calculate essential values each iteration of the loop.
// Decrement counter
TailCounter = _Sub(TailCounter, _Constant(1));
// First thing we need to do is finish this block and jump to the start of the loop.
_Jump(LoopHead);
// Store the counter so we don't have to deal with PHI here
_StoreContext(GPRClass, 8, offsetof(FEXCore::Core::CPUState, gregs[FEXCore::X86State::REG_RCX]), TailCounter);
SetCurrentCodeBlock(LoopHead);
{
OrderedNode *Counter = _LoadContext(8, offsetof(FEXCore::Core::CPUState, gregs[FEXCore::X86State::REG_RCX]), GPRClass);
auto ZeroConst = _Constant(0);
auto SizeConst = _Constant(Size);
auto NegSizeConst = _Constant(-Size);
// Can we end the block?
auto CanLeaveCond = _Select(FEXCore::IR::COND_EQ,
Counter, ZeroConst,
_Constant(1), ZeroConst);
// Calculate direction.
auto DF = GetRFLAG(FEXCore::X86State::RFLAG_DF_LOC);
auto PtrDir = _Select(FEXCore::IR::COND_EQ,
DF, _Constant(0),
SizeConst, NegSizeConst);
_CondJump(CanLeaveCond, LoopEnd, LoopTail);
}
// Offset the pointer
TailDest = _Add(TailDest, PtrDir);
_StoreContext(GPRClass, 8, offsetof(FEXCore::Core::CPUState, gregs[FEXCore::X86State::REG_RDI]), TailDest);
SetCurrentCodeBlock(LoopTail);
{
OrderedNode *Src = LoadSource(GPRClass, Op, Op->Src[0], Op->Flags, -1);
OrderedNode *Dest = _LoadContext(8, offsetof(FEXCore::Core::CPUState, gregs[FEXCore::X86State::REG_RDI]), GPRClass);
// Jump back to the start, we have more work to do
_Jump(LoopHead);
}
// Store to memory where RDI points
_StoreMem(GPRClass, Size, Dest, Src, Size);
// Make sure to start a new block after ending this one
OrderedNode *TailCounter = _LoadContext(8, offsetof(FEXCore::Core::CPUState, gregs[FEXCore::X86State::REG_RCX]), GPRClass);
OrderedNode *TailDest = _LoadContext(8, offsetof(FEXCore::Core::CPUState, gregs[FEXCore::X86State::REG_RDI]), GPRClass);
SetCurrentCodeBlock(LoopEnd);
// Decrement counter
TailCounter = _Sub(TailCounter, _Constant(1));
// Store the counter so we don't have to deal with PHI here
_StoreContext(GPRClass, 8, offsetof(FEXCore::Core::CPUState, gregs[FEXCore::X86State::REG_RCX]), TailCounter);
auto SizeConst = _Constant(Size);
auto NegSizeConst = _Constant(-Size);
// Calculate direction.
auto DF = GetRFLAG(FEXCore::X86State::RFLAG_DF_LOC);
auto PtrDir = _Select(FEXCore::IR::COND_EQ,
DF, _Constant(0),
SizeConst, NegSizeConst);
// Offset the pointer
TailDest = _Add(TailDest, PtrDir);
_StoreContext(GPRClass, 8, offsetof(FEXCore::Core::CPUState, gregs[FEXCore::X86State::REG_RDI]), TailDest);
// Jump back to the start, we have more work to do
_Jump(LoopHead);
}
// Make sure to start a new block after ending this one
SetCurrentCodeBlock(LoopEnd);
}
}
void OpDispatchBuilder::MOVSOp(OpcodeArgs) {
+40
View File
@@ -0,0 +1,40 @@
%ifdef CONFIG
{
"RegData": {
"RAX": "0xF2F2F2F2F2F2F2F2",
"RDX": "0x0",
"RDI": "0xE0000018"
},
"MemoryRegions": {
"0x100000000": "4096"
}
}
%endif
mov rdx, 0xe0000000
mov rax, 0x4142434445464748
mov [rdx + 8 * 0], rax
mov rax, 0x5152535455565758
mov [rdx + 8 * 1], rax
mov rax, 0x0
mov [rdx + 8 * 2], rax
mov [rdx + 8 * 3], rax
lea rdi, [rdx + 8 * 2]
cld
mov rax, 0xF2
stosb ; rdi <- al
stosb
stosb
stosb
stosb
stosb
stosb
stosb
mov rax, [rdx + 8 * 2]
mov rdx, [rdx + 8 * 3]
hlt
+33
View File
@@ -0,0 +1,33 @@
%ifdef CONFIG
{
"RegData": {
"RAX": "0xF2F2F2F2F2F2F2F2",
"RDX": "0x0",
"RDI": "0xE0000018"
},
"MemoryRegions": {
"0x100000000": "4096"
}
}
%endif
mov rdx, 0xe0000000
mov rax, 0x4142434445464748
mov [rdx + 8 * 0], rax
mov rax, 0x5152535455565758
mov [rdx + 8 * 1], rax
mov rax, 0x0
mov [rdx + 8 * 2], rax
mov [rdx + 8 * 3], rax
lea rdi, [rdx + 8 * 2]
cld
mov rcx, 8
mov rax, 0xF2
rep stosb ; rdi <- rsi
mov rax, [rdx + 8 * 2]
mov rdx, [rdx + 8 * 3]
hlt
@@ -0,0 +1,33 @@
%ifdef CONFIG
{
"RegData": {
"RAX": "0xF2F2F2F2F2F2F2F2",
"RDX": "0x0",
"RDI": "0xE000000F"
},
"MemoryRegions": {
"0x100000000": "4096"
}
}
%endif
mov rdx, 0xe0000000
mov rax, 0x4142434445464748
mov [rdx + 8 * 0], rax
mov rax, 0x5152535455565758
mov [rdx + 8 * 1], rax
mov rax, 0x0
mov [rdx + 8 * 2], rax
mov [rdx + 8 * 3], rax
lea rdi, [rdx + 8 * 2 + 7]
std
mov rcx, 8
mov rax, 0xF2
rep stosb ; rdi <- rsi
mov rax, [rdx + 8 * 2]
mov rdx, [rdx + 8 * 3]
hlt
@@ -0,0 +1,33 @@
%ifdef CONFIG
{
"RegData": {
"RAX": "0xF1F2F3F4F1F2F3F4",
"RDX": "0x0",
"RDI": "0xE0000018"
},
"MemoryRegions": {
"0x100000000": "4096"
}
}
%endif
mov rdx, 0xe0000000
mov rax, 0x4142434445464748
mov [rdx + 8 * 0], rax
mov rax, 0x5152535455565758
mov [rdx + 8 * 1], rax
mov rax, 0x0
mov [rdx + 8 * 2], rax
mov [rdx + 8 * 3], rax
lea rdi, [rdx + 8 * 2]
cld
mov rax, 0xF1F2F3F4
stosd ; rdi <- eax
stosd
mov rax, [rdx + 8 * 2]
mov rdx, [rdx + 8 * 3]
hlt
@@ -0,0 +1,33 @@
%ifdef CONFIG
{
"RegData": {
"RAX": "0xF1F2F3F4F1F2F3F4",
"RDX": "0x0",
"RDI": "0xE0000018"
},
"MemoryRegions": {
"0x100000000": "4096"
}
}
%endif
mov rdx, 0xe0000000
mov rax, 0x4142434445464748
mov [rdx + 8 * 0], rax
mov rax, 0x5152535455565758
mov [rdx + 8 * 1], rax
mov rax, 0x0
mov [rdx + 8 * 2], rax
mov [rdx + 8 * 3], rax
lea rdi, [rdx + 8 * 2]
cld
mov rax, 0xF1F2F3F4
mov rcx, 2
rep stosd ; rdi <- eax
mov rax, [rdx + 8 * 2]
mov rdx, [rdx + 8 * 3]
hlt
@@ -0,0 +1,33 @@
%ifdef CONFIG
{
"RegData": {
"RAX": "0xF1F2F3F4F1F2F3F4",
"RDX": "0x0",
"RDI": "0xE000000C"
},
"MemoryRegions": {
"0x100000000": "4096"
}
}
%endif
mov rdx, 0xe0000000
mov rax, 0x4142434445464748
mov [rdx + 8 * 0], rax
mov rax, 0x5152535455565758
mov [rdx + 8 * 1], rax
mov rax, 0x0
mov [rdx + 8 * 2], rax
mov [rdx + 8 * 3], rax
lea rdi, [rdx + 8 * 2 + 4]
std
mov rax, 0xF1F2F3F4
mov rcx, 2
rep stosd ; rdi <- eax
mov rax, [rdx + 8 * 2]
mov rdx, [rdx + 8 * 3]
hlt
@@ -0,0 +1,32 @@
%ifdef CONFIG
{
"RegData": {
"RAX": "0xF1F2F3F4F5F6F7F8",
"RDX": "0x0",
"RDI": "0xE0000018"
},
"MemoryRegions": {
"0x100000000": "4096"
}
}
%endif
mov rdx, 0xe0000000
mov rax, 0x4142434445464748
mov [rdx + 8 * 0], rax
mov rax, 0x5152535455565758
mov [rdx + 8 * 1], rax
mov rax, 0x0
mov [rdx + 8 * 2], rax
mov [rdx + 8 * 3], rax
lea rdi, [rdx + 8 * 2]
cld
mov rax, 0xF1F2F3F4F5F6F7F8
stosq ; rdi <- rax
mov rax, [rdx + 8 * 2]
mov rdx, [rdx + 8 * 3]
hlt
@@ -0,0 +1,36 @@
%ifdef CONFIG
{
"RegData": {
"RAX": "0xF1F2F3F4F5F6F7F8",
"RDX": "0xF1F2F3F4F5F6F7F8",
"RSI": "0x0",
"RDI": "0xE0000020"
},
"MemoryRegions": {
"0x100000000": "4096"
}
}
%endif
mov rdx, 0xe0000000
mov rax, 0x4142434445464748
mov [rdx + 8 * 0], rax
mov rax, 0x5152535455565758
mov [rdx + 8 * 1], rax
mov rax, 0x0
mov [rdx + 8 * 2], rax
mov [rdx + 8 * 3], rax
mov [rdx + 8 * 4], rax
lea rdi, [rdx + 8 * 2]
cld
mov rax, 0xF1F2F3F4F5F6F7F8
mov rcx, 2
rep stosq ; rdi <- rax
mov rax, [rdx + 8 * 2]
mov rsi, [rdx + 8 * 4]
mov rdx, [rdx + 8 * 3]
hlt
@@ -0,0 +1,36 @@
%ifdef CONFIG
{
"RegData": {
"RAX": "0xF1F2F3F4F5F6F7F8",
"RDX": "0xF1F2F3F4F5F6F7F8",
"RSI": "0x0",
"RDI": "0xE0000008"
},
"MemoryRegions": {
"0x100000000": "4096"
}
}
%endif
mov rdx, 0xe0000000
mov rax, 0x4142434445464748
mov [rdx + 8 * 0], rax
mov rax, 0x5152535455565758
mov [rdx + 8 * 1], rax
mov rax, 0x0
mov [rdx + 8 * 2], rax
mov [rdx + 8 * 3], rax
mov [rdx + 8 * 4], rax
lea rdi, [rdx + 8 * 3]
std
mov rax, 0xF1F2F3F4F5F6F7F8
mov rcx, 2
rep stosq ; rdi <- rax
mov rax, [rdx + 8 * 2]
mov rsi, [rdx + 8 * 4]
mov rdx, [rdx + 8 * 3]
hlt
+35
View File
@@ -0,0 +1,35 @@
%ifdef CONFIG
{
"RegData": {
"RAX": "0xF1F2F1F2F1F2F1F2",
"RDX": "0x0",
"RDI": "0xE0000018"
},
"MemoryRegions": {
"0x100000000": "4096"
}
}
%endif
mov rdx, 0xe0000000
mov rax, 0x4142434445464748
mov [rdx + 8 * 0], rax
mov rax, 0x5152535455565758
mov [rdx + 8 * 1], rax
mov rax, 0x0
mov [rdx + 8 * 2], rax
mov [rdx + 8 * 3], rax
lea rdi, [rdx + 8 * 2]
cld
mov rax, 0xF1F2
stosw ; rdi <- ax
stosw
stosw
stosw
mov rax, [rdx + 8 * 2]
mov rdx, [rdx + 8 * 3]
hlt
@@ -0,0 +1,33 @@
%ifdef CONFIG
{
"RegData": {
"RAX": "0xF1F2F1F2F1F2F1F2",
"RDX": "0x0",
"RDI": "0xE0000018"
},
"MemoryRegions": {
"0x100000000": "4096"
}
}
%endif
mov rdx, 0xe0000000
mov rax, 0x4142434445464748
mov [rdx + 8 * 0], rax
mov rax, 0x5152535455565758
mov [rdx + 8 * 1], rax
mov rax, 0x0
mov [rdx + 8 * 2], rax
mov [rdx + 8 * 3], rax
lea rdi, [rdx + 8 * 2]
cld
mov rcx, 0x4
mov rax, 0xF1F2
rep stosw ; rdi <- ax
mov rax, [rdx + 8 * 2]
mov rdx, [rdx + 8 * 3]
hlt
@@ -0,0 +1,33 @@
%ifdef CONFIG
{
"RegData": {
"RAX": "0xF1F2F1F2F1F2F1F2",
"RDX": "0x0",
"RDI": "0xE000000E"
},
"MemoryRegions": {
"0x100000000": "4096"
}
}
%endif
mov rdx, 0xe0000000
mov rax, 0x4142434445464748
mov [rdx + 8 * 0], rax
mov rax, 0x5152535455565758
mov [rdx + 8 * 1], rax
mov rax, 0x0
mov [rdx + 8 * 2], rax
mov [rdx + 8 * 3], rax
lea rdi, [rdx + 8 * 2 + 6]
std
mov rcx, 0x4
mov rax, 0xF1F2
rep stosw ; rdi <- ax
mov rax, [rdx + 8 * 2]
mov rdx, [rdx + 8 * 3]
hlt