Merge pull request #386 from FEX-Emu/skmp/fix-shld-shrd

x86disp: Fix shld/shrd flags
This commit is contained in:
Ryan Houdek authored and GitHub committed 2020-09-16 12:36:51 -07:00
commit bfde44a288
13 files changed
+575 -31

No files matched your search

+60 -31
View File
@@ -1598,16 +1598,31 @@ void OpDispatchBuilder::SHLDOp(OpcodeArgs) {
else
Shift = _And(Shift, _Constant(0x1F));
auto CondJump = _CondJump(Shift);
// Do nothing if shift count is zero
auto JumpTarget = CreateNewCodeBlock();
SetTrueJumpTarget(CondJump, JumpTarget);
SetCurrentCodeBlock(JumpTarget);
auto ShiftRight = _Sub(_Constant(Size), Shift);
OrderedNode *Res{};
auto Tmp1 = _Lshl(Dest, Shift);
auto Tmp2 = _Lshr(Src, ShiftRight);
Res = _Or(Tmp1, Tmp2);
StoreResult(GPRClass, Op, Res, -1);
GenerateFlags_ShiftLeft(Op, _Bfe(Size, 0, Res), _Bfe(Size, 0, Dest), _Bfe(Size, 0, Src));
GenerateFlags_ShiftLeft(Op, _Bfe(Size, 0, Res), _Bfe(Size, 0, Dest), _Bfe(Size, 0, Shift));
auto Jump = _Jump();
auto NextJumpTarget = CreateNewCodeBlock();
SetJumpTarget(Jump, NextJumpTarget);
SetFalseJumpTarget(CondJump, NextJumpTarget);
SetCurrentCodeBlock(NextJumpTarget);
}
void OpDispatchBuilder::SHLDImmediateOp(OpcodeArgs) {
@@ -1625,17 +1640,19 @@ void OpDispatchBuilder::SHLDImmediateOp(OpcodeArgs) {
else
Shift &= 0x1F;
OrderedNode *ShiftLeft = _Constant(Shift);
auto ShiftRight = _Constant(Size - Shift);
if (Shift != 0) {
OrderedNode *ShiftLeft = _Constant(Shift);
auto ShiftRight = _Constant(Size - Shift);
OrderedNode *Res{};
auto Tmp1 = _Lshl(Dest, ShiftLeft);
auto Tmp2 = _Lshr(Src, ShiftRight);
Res = _Or(Tmp1, Tmp2);
OrderedNode *Res{};
auto Tmp1 = _Lshl(Dest, ShiftLeft);
auto Tmp2 = _Lshr(Src, ShiftRight);
Res = _Or(Tmp1, Tmp2);
StoreResult(GPRClass, Op, Res, -1);
StoreResult(GPRClass, Op, Res, -1);
GenerateFlags_ShiftLeftImmediate(Op, _Bfe(Size, 0, Res), _Bfe(Size, 0, Dest), Shift);
GenerateFlags_ShiftLeftImmediate(Op, _Bfe(Size, 0, Res), _Bfe(Size, 0, Dest), Shift);
}
}
void OpDispatchBuilder::SHRDOp(OpcodeArgs) {
@@ -1652,6 +1669,14 @@ void OpDispatchBuilder::SHRDOp(OpcodeArgs) {
else
Shift = _And(Shift, _Constant(0x1F));
auto CondJump = _CondJump(Shift);
// Do nothing if shift count is zero
auto JumpTarget = CreateNewCodeBlock();
SetTrueJumpTarget(CondJump, JumpTarget);
SetCurrentCodeBlock(JumpTarget);
auto ShiftLeft = _Sub(_Constant(Size), Shift);
OrderedNode *Res{};
@@ -1660,7 +1685,13 @@ void OpDispatchBuilder::SHRDOp(OpcodeArgs) {
Res = _Or(Tmp1, Tmp2);
StoreResult(GPRClass, Op, Res, -1);
GenerateFlags_ShiftRight(Op, _Bfe(Size, 0, Res), _Bfe(Size, 0, Dest), _Bfe(Size, 0, Src));
GenerateFlags_ShiftRight(Op, _Bfe(Size, 0, Res), _Bfe(Size, 0, Dest), _Bfe(Size, 0, Shift));
auto Jump = _Jump();
auto NextJumpTarget = CreateNewCodeBlock();
SetJumpTarget(Jump, NextJumpTarget);
SetFalseJumpTarget(CondJump, NextJumpTarget);
SetCurrentCodeBlock(NextJumpTarget);
}
void OpDispatchBuilder::SHRDImmediateOp(OpcodeArgs) {
@@ -1678,17 +1709,19 @@ void OpDispatchBuilder::SHRDImmediateOp(OpcodeArgs) {
else
Shift = Op->Src[1].TypeLiteral.Literal & 0x1F;
OrderedNode *ShiftRight = _Constant(Shift);
auto ShiftLeft = _Constant(Size - Shift);
if (Shift != 0) {
OrderedNode *ShiftRight = _Constant(Shift);
auto ShiftLeft = _Constant(Size - Shift);
OrderedNode *Res{};
auto Tmp1 = _Lshr(Dest, ShiftRight);
auto Tmp2 = _Lshl(Src, ShiftLeft);
Res = _Or(Tmp1, Tmp2);
OrderedNode *Res{};
auto Tmp1 = _Lshr(Dest, ShiftRight);
auto Tmp2 = _Lshl(Src, ShiftLeft);
Res = _Or(Tmp1, Tmp2);
StoreResult(GPRClass, Op, Res, -1);
StoreResult(GPRClass, Op, Res, -1);
GenerateFlags_ShiftRightImmediate(Op, _Bfe(Size, 0, Res), _Bfe(Size, 0, Dest), Shift);
GenerateFlags_ShiftRightImmediate(Op, _Bfe(Size, 0, Res), _Bfe(Size, 0, Dest), Shift);
}
}
template<bool SHR1Bit>
@@ -4863,16 +4896,14 @@ void OpDispatchBuilder::GenerateFlags_ShiftLeft(FEXCore::X86Tables::DecodedOp Op
// SF
{
auto SignBitConst = _Constant(GetSrcSize(Op) * 8 - 1);
SetRFLAG<FEXCore::X86State::RFLAG_SF_LOC>(_Bfe(1, GetSrcSize(Op) * 8 - 1, Res));
}
auto LshrOp = _Lshr(Res, SignBitConst);
SetRFLAG<FEXCore::X86State::RFLAG_SF_LOC>(LshrOp);
// OF
// OF
{
// In the case of left shift. OF is only set from the result of <Top Source Bit> XOR <Top Result Bit>
// When Shift > 1 then OF is undefined
auto SourceBit = _Bfe(1, GetSrcSize(Op) * 8 - 1, Src1);
SetRFLAG<FEXCore::X86State::RFLAG_OF_LOC>(_Xor(SourceBit, LshrOp));
SetRFLAG<FEXCore::X86State::RFLAG_OF_LOC>(_Bfe(1, GetSrcSize(Op) * 8 - 1, _Xor(Src1, Res)));
}
auto Jump = _Jump();
@@ -4923,17 +4954,15 @@ void OpDispatchBuilder::GenerateFlags_ShiftRight(FEXCore::X86Tables::DecodedOp O
// SF
{
auto SignBitConst = _Constant(GetSrcSize(Op) * 8 - 1);
auto LshrOp = _Lshr(Res, SignBitConst);
SetRFLAG<FEXCore::X86State::RFLAG_SF_LOC>(LshrOp);
SetRFLAG<FEXCore::X86State::RFLAG_SF_LOC>(_Bfe(1, GetSrcSize(Op) * 8 - 1, Res));
}
// OF
{
// Only defined when Shift is 1 else undefined
// Is set to the MSB of the original value
SetRFLAG<FEXCore::X86State::RFLAG_OF_LOC>(_Bfe(1, GetSrcSize(Op) * 8 - 1, Src1));
// OF flag is set if a sign change occurred
SetRFLAG<FEXCore::X86State::RFLAG_OF_LOC>(_Bfe(1, GetSrcSize(Op) * 8 - 1, _Xor(Src1, Res)));
}
auto Jump = _Jump();
+22
View File
@@ -0,0 +1,22 @@
%ifdef CONFIG
{
"RegData": {
"R15": "0xFFFFFFFFFFFFFFFF",
"R14": "0x4141414141410000",
"R13": "0",
"R12": "0"
}
}
%endif
mov cl, 0
mov r15, -1
mov r14, 0x4141414141410000
mov r13, 0
mov r12, 0
shld r14w, r15w, cl
shld r13d, r15d, cl
shld r12, r15, cl
hlt
+35
View File
@@ -0,0 +1,35 @@
%ifdef CONFIG
{
"RegData": {
"R15": "0xFFFFFFFFFFFFFFFF",
"R14": "0x4141414141410000",
"R13": "0",
"R12": "0",
"R11": "0"
}
}
%endif
mov cl, 0
mov r15, -1
mov r14, 0x4141414141410000
mov r13, 0
mov r12, 0
mov r11, 0
; Get the incoming flags
mov rax, 0
lahf
mov r11, rax
shld r14w, r15w, cl
shld r13d, r15d, cl
shld r12, r15, cl
; Get the outgoing flags
; None should have changed
mov rax, 0
lahf
xor r11, rax
hlt
+113
View File
@@ -0,0 +1,113 @@
%ifdef CONFIG
{
"RegData": {
"r10": "1",
"RBX": "1",
"RDX": "1",
"RSI": "1",
"RBP": "1",
"RSP": "0",
"R8": "0",
"r9": "0"
}
}
%endif
mov cl, 1
mov r15, -1
mov r14, 0xFFFFFFFFFFFF4000
mov r13, 0xFFFFFFFF40000000
mov r12, 0x4000000000000000
mov r10, 0
mov rbx, 0
mov rdx, 0
mov rsi, 0
mov rdi, 0
mov rbp, 0
mov rsp, 0
mov r8, 0
mov r9, 0
mov r11, 1
; Sign from 0->1 should set OF
; Let's clear OF really quick
mov rax, 0
ror rax, 1
shld r14w, r15w, cl
cmovo r10, r11
; Let's clear OF really quick
mov rax, 0
ror rax, 1
shld r13d, r15d, cl
cmovo rbx, r11
; Let's clear OF really quick
mov rax, 0
ror rax, 1
shld r12, r15, cl
cmovo rdx, r11
; Sign from 1->0 should set OF
mov r15, -1
mov r14, 0xFFFFFFFFFFFF8000
mov r13, 0xFFFFFFFF80000000
mov r12, 0x8000000000000000
; Let's clear OF really quick
mov rax, 0
ror rax, 1
shld r14w, r15w, cl
cmovo rsi, r11
; Let's clear OF really quick
mov rax, 0
ror rax, 1
shld r13d, r15d, cl
cmovo rdi, r11
; Let's clear OF really quick
mov rax, 0
ror rax, 1
shld r12, r15, cl
cmovo rbp, r11
; Sign from 0->0 should NOT set OF
mov r15, -1
mov r14, 0xFFFFFFFFFFFF0000
mov r13, 0xFFFFFFFF00000000
mov r12, 0x0000000000000000
; Let's clear OF really quick
mov rax, 0
ror rax, 1
shld r14w, r15w, cl
cmovo rsp, r11
; Let's clear OF really quick
mov rax, 0
ror rax, 1
shld r13d, r15d, cl
cmovo r8, r11
; Let's clear OF really quick
mov rax, 0
ror rax, 1
shld r12, r15, cl
cmovo r9, r11
hlt
+29
View File
@@ -0,0 +1,29 @@
%ifdef CONFIG
{
"RegData": {
"RAX": "1",
"RBX": "1",
"RDX": "1"
}
}
%endif
mov cl, 2
mov r15, -1
mov r14, 0x4141414141414000
mov r13, 0xFFFFFFFF40000000
mov r12, 0x4000000000000000
mov rax, 0
mov rbx, 0
mov rdx, 0
mov rsi, 1
shld r14w, r15w, cl
cmovc rax, rsi
shld r13d, r15d, cl
cmovc rbx, rsi
shld r12, r15, cl
cmovc rdx, rsi
hlt
+29
View File
@@ -0,0 +1,29 @@
%ifdef CONFIG
{
"RegData": {
"RAX": "1",
"RBX": "1",
"RDX": "1"
}
}
%endif
mov cl, 2
mov r15, 0
mov r14, 0x4141414141414000
mov r13, 0xFFFFFFFF40000000
mov r12, 0x4000000000000000
mov rax, 0
mov rbx, 0
mov rdx, 0
mov rsi, 1
shld r14w, r15w, cl
cmovz rax, rsi
shld r13d, r15d, cl
cmovz rbx, rsi
shld r12, r15, cl
cmovz rdx, rsi
hlt
+29
View File
@@ -0,0 +1,29 @@
%ifdef CONFIG
{
"RegData": {
"RAX": "1",
"RBX": "1",
"RDX": "1"
}
}
%endif
mov cl, 2
mov r15, 0
mov r14, 0x4141414141412000
mov r13, 0xFFFFFFFF20000000
mov r12, 0x2000000000000000
mov rax, 0
mov rbx, 0
mov rdx, 0
mov rsi, 1
shld r14w, r15w, cl
cmovs rax, rsi
shld r13d, r15d, cl
cmovs rbx, rsi
shld r12, r15, cl
cmovs rdx, rsi
hlt
+22
View File
@@ -0,0 +1,22 @@
%ifdef CONFIG
{
"RegData": {
"R15": "0xFFFFFFFFFFFFFFFF",
"R14": "0x4141414141410000",
"R13": "0",
"R12": "0"
}
}
%endif
mov cl, 0
mov r15, -1
mov r14, 0x4141414141410000
mov r13, 0
mov r12, 0
shrd r14w, r15w, cl
shrd r13d, r15d, cl
shrd r12, r15, cl
hlt
+35
View File
@@ -0,0 +1,35 @@
%ifdef CONFIG
{
"RegData": {
"R15": "0xFFFFFFFFFFFFFFFF",
"R14": "0x4141414141410000",
"R13": "0",
"R12": "0",
"R11": "0"
}
}
%endif
mov cl, 0
mov r15, -1
mov r14, 0x4141414141410000
mov r13, 0
mov r12, 0
mov r11, 0
; Get the incoming flags
mov rax, 0
lahf
mov r11, rax
shrd r14w, r15w, cl
shrd r13d, r15d, cl
shrd r12, r15, cl
; Get the outgoing flags
; None should have changed
mov rax, 0
lahf
xor r11, rax
hlt
+113
View File
@@ -0,0 +1,113 @@
%ifdef CONFIG
{
"RegData": {
"r10": "1",
"RBX": "1",
"RDX": "1",
"RSI": "1",
"RBP": "1",
"RSP": "0",
"R8": "0",
"r9": "0"
}
}
%endif
mov cl, 1
mov r15, -1
mov r14, 0xFFFFFFFFFFFF0000
mov r13, 0xFFFFFFFF00000000
mov r12, 0
mov r10, 0
mov rbx, 0
mov rdx, 0
mov rsi, 0
mov rdi, 0
mov rbp, 0
mov rsp, 0
mov r8, 0
mov r9, 0
mov r11, 1
; Sign from 0->1 should set OF
; Let's clear OF really quick
mov rax, 0
ror rax, 1
shrd r14w, r15w, cl
cmovo r10, r11
; Let's clear OF really quick
mov rax, 0
ror rax, 1
shrd r13d, r15d, cl
cmovo rbx, r11
; Let's clear OF really quick
mov rax, 0
ror rax, 1
shrd r12, r15, cl
cmovo rdx, r11
; Sign from 1->0 should set OF
mov r15, 0
mov r14, 0xFFFFFFFFFFFF8000
mov r13, 0xFFFFFFFF80000000
mov r12, 0x8000000000000000
; Let's clear OF really quick
mov rax, 0
ror rax, 1
shrd r14w, r15w, cl
cmovo rsi, r11
; Let's clear OF really quick
mov rax, 0
ror rax, 1
shrd r13d, r15d, cl
cmovo rdi, r11
; Let's clear OF really quick
mov rax, 0
ror rax, 1
shrd r12, r15, cl
cmovo rbp, r11
; Sign from 0->0 should NOT set OF
mov r15, 0xFFFFFFFFFFFFFFFE
mov r14, 0xFFFFFFFFFFFF0000
mov r13, 0xFFFFFFFF00000000
mov r12, 0x0000000000000000
; Let's clear OF really quick
mov rax, 0
ror rax, 1
shrd r14w, r15w, cl
cmovo rsp, r11
; Let's clear OF really quick
mov rax, 0
ror rax, 1
shrd r13d, r15d, cl
cmovo r8, r11
; Let's clear OF really quick
mov rax, 0
ror rax, 1
shrd r12, r15, cl
cmovo r9, r11
hlt
+29
View File
@@ -0,0 +1,29 @@
%ifdef CONFIG
{
"RegData": {
"RAX": "1",
"RBX": "1",
"RDX": "1"
}
}
%endif
mov cl, 2
mov r15, -1
mov r14, 0x4141414141410002
mov r13, 0xFFFFFFFF00000002
mov r12, 0x0000000000000002
mov rax, 0
mov rbx, 0
mov rdx, 0
mov rsi, 1
shrd r14w, r15w, cl
cmovc rax, rsi
shrd r13d, r15d, cl
cmovc rbx, rsi
shrd r12, r15, cl
cmovc rdx, rsi
hlt
+29
View File
@@ -0,0 +1,29 @@
%ifdef CONFIG
{
"RegData": {
"RAX": "1",
"RBX": "1",
"RDX": "1"
}
}
%endif
mov cl, 2
mov r15, 0
mov r14, 0x4141414141410002
mov r13, 0xFFFFFFFF00000002
mov r12, 0x0000000000000002
mov rax, 0
mov rbx, 0
mov rdx, 0
mov rsi, 1
shrd r14w, r15w, cl
cmovz rax, rsi
shrd r13d, r15d, cl
cmovz rbx, rsi
shrd r12, r15, cl
cmovz rdx, rsi
hlt
+30
View File
@@ -0,0 +1,30 @@
%ifdef CONFIG
{
"RegData": {
"RAX": "1",
"RBX": "1",
"RDX": "1"
}
}
%endif
mov cl, 2
mov r15, 0xFFFFFFFFFFFFFFF2
mov r14, 0x4141414141410000
mov r13, 0xFFFFFFFF00000000
mov r12, 0x0000000000000000
mov rax, 0
mov rbx, 0
mov rdx, 0
mov rsi, 1
shrd r14w, r15w, cl
cmovs rax, rsi
shrd r13d, r15d, cl
cmovs rbx, rsi
shrd r12, r15, cl
cmovs rdx, rsi
hlt